]> git.sesse.net Git - vlc/blob - modules/visualization/galaktos/custom_wave.c
Remove stdio while we're at it.
[vlc] / modules / visualization / galaktos / custom_wave.c
1 /*****************************************************************************
2  * custom_wave.c:
3  *****************************************************************************
4  * Copyright (C) 2004 the VideoLAN team
5  * $Id$
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
25
26
27
28 #include "common.h"
29 #include "fatal.h"
30
31 #include "param_types.h"
32 #include "param.h"
33
34 #include "expr_types.h"
35 #include "eval.h"
36
37 #include "splaytree_types.h"
38 #include "splaytree.h"
39 #include "tree_types.h"
40
41 #include "per_frame_eqn_types.h"
42 #include "per_frame_eqn.h"
43
44 #include "init_cond_types.h"
45 #include "init_cond.h"
46
47 #include "preset_types.h"
48
49 #include "custom_wave_types.h"
50 #include "custom_wave.h"
51
52 #include "init_cond_types.h"
53 #include "init_cond.h"
54
55 #include "engine_vars.h"
56 #define MAX_SAMPLE_SIZE 4096
57
58 extern int mesh_i;
59
60 custom_wave_t * interface_wave = NULL;
61 int interface_id = 0;
62 extern preset_t * active_preset;
63 inline void eval_custom_wave_init_conds(custom_wave_t * custom_wave);
64 void load_unspec_init_cond(param_t * param);
65 void destroy_per_point_eqn_tree(splaytree_t * tree);
66 void destroy_param_db_tree(splaytree_t * tree);
67 void destroy_per_frame_eqn_tree(splaytree_t * tree);
68 void destroy_per_frame_init_eqn_tree(splaytree_t * tree);
69 void destroy_init_cond_tree(splaytree_t * tree);
70 inline void evalPerPointEqn(per_point_eqn_t * per_point_eqn);
71
72 custom_wave_t * new_custom_wave(int id) {
73
74   custom_wave_t * custom_wave;
75   param_t * param;
76   
77   if ((custom_wave = (custom_wave_t*)malloc(sizeof(custom_wave_t))) == NULL)
78     return NULL;
79
80   custom_wave->id = id;
81   custom_wave->per_frame_count = 0;
82
83   custom_wave->samples = 512;
84   custom_wave->bSpectrum = 0;
85   custom_wave->enabled = 1;
86   custom_wave->sep = 1;
87   custom_wave->smoothing = 0.0;
88   custom_wave->bUseDots = 0;
89   custom_wave->bAdditive = 0;
90   custom_wave->r = custom_wave->g = custom_wave->b = custom_wave->a = 0.0;
91   custom_wave->scaling = 1.0;
92   custom_wave->per_frame_eqn_string_index = 0;
93   custom_wave->per_frame_init_eqn_string_index = 0;
94   custom_wave->per_point_eqn_string_index = 0;
95
96   custom_wave->r_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
97   custom_wave->g_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
98   custom_wave->b_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
99   custom_wave->a_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
100   custom_wave->x_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
101   custom_wave->y_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
102   custom_wave->value1 = malloc(MAX_SAMPLE_SIZE*sizeof(double));
103   custom_wave->value2 = malloc(MAX_SAMPLE_SIZE*sizeof(double));
104   custom_wave->sample_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
105
106   /* Initialize tree data structures */
107   
108   if ((custom_wave->param_tree = 
109        create_splaytree(compare_string, copy_string, free_string)) == NULL) {
110     free_custom_wave(custom_wave);
111     return NULL;
112   }
113
114   if ((custom_wave->per_point_eqn_tree = 
115        create_splaytree(compare_int, copy_int, free_int)) == NULL) {
116     free_custom_wave(custom_wave);
117     return NULL;
118   }
119
120   if ((custom_wave->per_frame_eqn_tree = 
121        create_splaytree(compare_int, copy_int, free_int)) == NULL) {
122     free_custom_wave(custom_wave);
123     return NULL;
124   }
125
126   if ((custom_wave->init_cond_tree = 
127        create_splaytree(compare_string, copy_string, free_string)) == NULL) {
128     free_custom_wave(custom_wave);
129     return NULL;
130   }
131   
132   if ((custom_wave->per_frame_init_eqn_tree = 
133        create_splaytree(compare_string, copy_string, free_string)) == NULL) {
134     free_custom_wave(custom_wave);
135     return NULL;
136   }
137
138   
139   /* Start: Load custom wave parameters */
140
141   if ((param = new_param_double("r", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->r, custom_wave->r_mesh, 1.0, 0.0, .5)) == NULL) {
142     free_custom_wave(custom_wave);
143     return NULL;
144   }
145
146   if (insert_param(param, custom_wave->param_tree) < 0) {
147     free_custom_wave(custom_wave);
148     return NULL;
149   }
150  
151   if ((param = new_param_double("g", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->g,  custom_wave->g_mesh, 1.0, 0.0, .5)) == NULL){
152     free_custom_wave(custom_wave);
153     return NULL;
154   }
155
156   if (insert_param(param, custom_wave->param_tree) < 0) {
157     free_custom_wave(custom_wave);
158     return NULL;
159   }
160
161   if ((param = new_param_double("b", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->b,  custom_wave->b_mesh, 1.0, 0.0, .5)) == NULL){
162     free_custom_wave(custom_wave);
163     return NULL;                                       
164   }
165
166   if (insert_param(param, custom_wave->param_tree) < 0) {
167     free_custom_wave(custom_wave);
168     return NULL;
169   }
170
171   if ((param = new_param_double("a", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->a,  custom_wave->a_mesh, 1.0, 0.0, .5)) == NULL){
172     free_custom_wave(custom_wave);
173     return NULL;
174   }
175   
176   if (insert_param(param, custom_wave->param_tree) < 0) {
177     free_custom_wave(custom_wave);
178     return NULL;
179   }
180
181   if ((param = new_param_double("x", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->x,  custom_wave->x_mesh, 1.0, 0.0, .5)) == NULL) {
182     free_custom_wave(custom_wave);
183     return NULL;
184   }
185
186   if (insert_param(param, custom_wave->param_tree) < 0) {
187     free_custom_wave(custom_wave);
188     return NULL;
189   }
190
191   if ((param = new_param_double("y", P_FLAG_DONT_FREE_MATRIX | P_FLAG_PER_POINT, &custom_wave->y,  custom_wave->y_mesh, 1.0, 0.0, .5)) == NULL) {
192     free_custom_wave(custom_wave);
193     return NULL;
194   }
195
196   if (insert_param(param, custom_wave->param_tree) < 0) {
197     free_custom_wave(custom_wave);
198     return NULL;
199   }
200
201   if ((param = new_param_bool("enabled", P_FLAG_NONE, &custom_wave->enabled, 1, 0, 0)) == NULL) {
202     free_custom_wave(custom_wave);
203     return NULL;
204   }
205
206   if (insert_param(param, custom_wave->param_tree) < 0) {
207     free_custom_wave(custom_wave);
208     return NULL;
209   }
210
211   if ((param = new_param_int("sep", P_FLAG_NONE, &custom_wave->sep, 100, -100, 0)) == NULL) {
212     free_custom_wave(custom_wave);
213     return NULL;
214   }
215
216   if (insert_param(param, custom_wave->param_tree) < 0) {
217     free_custom_wave(custom_wave);
218     return NULL;
219   }
220
221   if ((param = new_param_bool("bSpectrum", P_FLAG_NONE, &custom_wave->bSpectrum, 1, 0, 0)) == NULL) {
222     free_custom_wave(custom_wave);
223     return NULL;
224   }
225
226   if (insert_param(param, custom_wave->param_tree) < 0) {
227     free_custom_wave(custom_wave);
228     return NULL;
229   }
230
231   if ((param = new_param_bool("bDrawThick", P_FLAG_NONE, &custom_wave->bDrawThick, 1, 0, 0)) == NULL) {
232     free_custom_wave(custom_wave);
233     return NULL;
234   }
235
236   if (insert_param(param, custom_wave->param_tree) < 0) {
237     free_custom_wave(custom_wave);
238     return NULL;
239   }
240
241   if ((param = new_param_bool("bUseDots", P_FLAG_NONE, &custom_wave->bUseDots, 1, 0, 0)) == NULL) {
242     free_custom_wave(custom_wave);
243     return NULL;
244   }
245
246   if (insert_param(param, custom_wave->param_tree) < 0) {
247     free_custom_wave(custom_wave);
248     return NULL;
249   }
250  
251   if ((param = new_param_bool("bAdditive", P_FLAG_NONE, &custom_wave->bAdditive, 1, 0, 0)) == NULL) {
252     free_custom_wave(custom_wave);
253     return NULL;
254   }
255
256   if (insert_param(param, custom_wave->param_tree) < 0) {
257     free_custom_wave(custom_wave);
258     return NULL;
259   }
260
261   if ((param = new_param_int("samples", P_FLAG_NONE, &custom_wave->samples, 2048, 1, 512)) == NULL) {
262     free_custom_wave(custom_wave);
263     return NULL;
264   }
265  
266   if (insert_param(param, custom_wave->param_tree) < 0) {
267     free_custom_wave(custom_wave);
268     return NULL;
269   }
270
271   if ((param = new_param_double("sample", P_FLAG_READONLY | P_FLAG_DONT_FREE_MATRIX | P_FLAG_ALWAYS_MATRIX | P_FLAG_PER_POINT,
272                                 &custom_wave->sample, custom_wave->sample_mesh, 1.0, 0.0, 0.0)) == NULL) {
273     free_custom_wave(custom_wave);
274     return NULL;
275   }
276  
277  if (insert_param(param, custom_wave->param_tree) < 0) {
278     printf("failed to insert sample\n");
279     free_custom_wave(custom_wave);
280     return NULL;
281   }
282
283   if ((param = new_param_double("value1", P_FLAG_READONLY | P_FLAG_DONT_FREE_MATRIX | P_FLAG_ALWAYS_MATRIX | P_FLAG_PER_POINT, &custom_wave->v1, custom_wave->value1, 1.0, -1.0, 0.0)) == NULL) {
284     free_custom_wave(custom_wave);
285     return NULL;
286   }
287
288   if (insert_param(param, custom_wave->param_tree) < 0) {
289     free_custom_wave(custom_wave);
290     return NULL;
291   }
292
293   if ((param = new_param_double("value2", P_FLAG_READONLY | P_FLAG_DONT_FREE_MATRIX | P_FLAG_ALWAYS_MATRIX | P_FLAG_PER_POINT, &custom_wave->v2, custom_wave->value2, 1.0, -1.0, 0.0)) == NULL) {
294     free_custom_wave(custom_wave);
295     return NULL;
296   }
297
298   if (insert_param(param, custom_wave->param_tree) < 0) {
299     free_custom_wave(custom_wave);
300     return NULL;
301   }
302
303   if ((param = new_param_double("smoothing", P_FLAG_NONE, &custom_wave->smoothing, NULL, 1.0, 0.0, 0.0)) == NULL) {
304     free_custom_wave(custom_wave);
305     return NULL;
306   }
307
308   if (insert_param(param, custom_wave->param_tree) < 0) {
309     free_custom_wave(custom_wave);
310     return NULL;
311   }
312
313   if ((param = new_param_double("scaling", P_FLAG_NONE, &custom_wave->scaling, NULL, MAX_DOUBLE_SIZE, 0.0, 1.0)) == NULL) {
314     free_custom_wave(custom_wave);
315     return NULL;
316   }
317
318   if (insert_param(param, custom_wave->param_tree) < 0) {
319     free_custom_wave(custom_wave);
320     return NULL;
321   }
322  
323   if ((param = new_param_double("t1", P_FLAG_PER_POINT | P_FLAG_TVAR, &custom_wave->t1, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
324     free_custom_wave(custom_wave);
325     return NULL;
326   }
327
328   if (insert_param(param, custom_wave->param_tree) < 0) {
329     free_custom_wave(custom_wave);
330     return NULL;
331   }
332
333   if ((param = new_param_double("t2",  P_FLAG_PER_POINT |P_FLAG_TVAR, &custom_wave->t2, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
334     free_custom_wave(custom_wave);
335     return NULL;
336   }
337
338   if (insert_param(param, custom_wave->param_tree) < 0) {
339     free_custom_wave(custom_wave);
340     return NULL;
341   }
342
343   if ((param = new_param_double("t3",  P_FLAG_PER_POINT |P_FLAG_TVAR, &custom_wave->t3, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
344     free_custom_wave(custom_wave);
345     return NULL;
346   }
347
348   if (insert_param(param, custom_wave->param_tree) < 0) {
349     free_custom_wave(custom_wave);
350     return NULL;
351   }
352   if ((param = new_param_double("t4",  P_FLAG_PER_POINT |P_FLAG_TVAR, &custom_wave->t4, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
353     free_custom_wave(custom_wave);
354     return NULL;
355   }
356
357   if (insert_param(param, custom_wave->param_tree) < 0) {
358     free_custom_wave(custom_wave);
359     return NULL;
360   }
361   if ((param = new_param_double("t5", P_FLAG_TVAR, &custom_wave->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
362     free_custom_wave(custom_wave);
363     return NULL;
364   }
365  
366   if (insert_param(param, custom_wave->param_tree) < 0) {
367     free_custom_wave(custom_wave);
368     return NULL;
369   }
370   if ((param = new_param_double("t6", P_FLAG_TVAR | P_FLAG_PER_POINT, &custom_wave->t6, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
371     free_custom_wave(custom_wave);
372     return NULL;
373   }
374
375   if (insert_param(param, custom_wave->param_tree) < 0) {
376     free_custom_wave(custom_wave);
377     return NULL;
378   }
379   if ((param = new_param_double("t7", P_FLAG_TVAR | P_FLAG_PER_POINT, &custom_wave->t7, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
380     free_custom_wave(custom_wave);
381     return NULL;
382   }
383
384   if (insert_param(param, custom_wave->param_tree) < 0) {
385     free_custom_wave(custom_wave);
386     return NULL;
387   }
388
389   if ((param = new_param_double("t8", P_FLAG_TVAR | P_FLAG_PER_POINT, &custom_wave->t8, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
390     free_custom_wave(custom_wave);
391     return NULL;
392   }
393
394   if (insert_param(param, custom_wave->param_tree) < 0) {
395     free_custom_wave(custom_wave);
396     return NULL;
397   }
398   
399   /* End of parameter loading. Note that the read only parameters associated
400      with custom waves (ie, sample) are global variables, and not specific to 
401      the custom wave datastructure. */
402
403
404   return custom_wave;
405
406 }
407
408 void destroy_per_frame_init_eqn_tree(splaytree_t * tree) {
409
410   if (!tree)
411     return;
412
413   splay_traverse(free_init_cond, tree);
414   destroy_splaytree(tree);
415
416 }
417
418
419 void destroy_per_point_eqn_tree(splaytree_t * tree) {
420
421   if (!tree)
422     return;
423
424   splay_traverse(free_per_point_eqn, tree);
425   destroy_splaytree(tree);
426
427 }
428
429 void destroy_init_cond_tree(splaytree_t * tree) {
430
431   if (!tree)
432     return;
433
434   splay_traverse(free_init_cond, tree);
435   destroy_splaytree(tree);
436
437 }
438
439 void destroy_per_frame_eqn_tree(splaytree_t * tree) {
440
441
442   if (!tree)
443     return;
444
445   splay_traverse(free_per_frame_eqn, tree);
446   destroy_splaytree(tree);
447
448 }
449
450
451 void destroy_param_db_tree(splaytree_t * tree) {
452
453   if (!tree)
454     return;
455
456   splay_traverse(free_param, tree);
457   destroy_splaytree(tree);
458
459 }
460
461 /* Frees a custom wave form object */
462 void free_custom_wave(custom_wave_t * custom_wave) {
463
464   if (custom_wave == NULL)
465     return;
466
467   if (custom_wave->param_tree == NULL)
468     return;
469
470   destroy_per_point_eqn_tree(custom_wave->per_point_eqn_tree);
471   destroy_per_frame_eqn_tree(custom_wave->per_frame_eqn_tree);
472   destroy_init_cond_tree(custom_wave->init_cond_tree);
473   destroy_param_db_tree(custom_wave->param_tree);
474   destroy_per_frame_init_eqn_tree(custom_wave->per_frame_init_eqn_tree);
475
476   free(custom_wave->r_mesh);
477   free(custom_wave->g_mesh);
478   free(custom_wave->b_mesh);
479   free(custom_wave->a_mesh);
480   free(custom_wave->x_mesh);
481   free(custom_wave->y_mesh);
482   free(custom_wave->value1);
483   free(custom_wave->value2);
484   free(custom_wave->sample_mesh);
485
486   free(custom_wave);
487
488   return;
489
490 }
491
492
493
494 int add_per_point_eqn(char * name, gen_expr_t * gen_expr, custom_wave_t * custom_wave) {
495
496   per_point_eqn_t * per_point_eqn;
497   int index;
498   param_t * param = NULL;
499
500   /* Argument checks */
501   if (custom_wave == NULL)
502           return FAILURE;
503   if (gen_expr == NULL)
504           return FAILURE;
505   if (name == NULL)
506           return FAILURE;
507   
508  if (CUSTOM_WAVE_DEBUG) printf("add_per_point_eqn: per pixel equation (name = \"%s\")\n", name);
509
510  /* Search for the parameter so we know what matrix the per pixel equation is referencing */
511
512  if ((param = find_param_db(name, custom_wave->param_tree, TRUE)) == NULL) {
513    if (CUSTOM_WAVE_DEBUG) printf("add_per_point_eqn: failed to allocate a new parameter!\n");
514    return FAILURE;
515  
516  }       
517
518  /* Find most largest index in the splaytree */
519  if ((per_point_eqn = splay_find_max(custom_wave->per_point_eqn_tree)) == NULL)
520    index = 0;
521  else
522    index = per_point_eqn->index+1;
523
524  /* Create the per pixel equation given the index, parameter, and general expression */
525  if ((per_point_eqn = new_per_point_eqn(index, param, gen_expr)) == NULL)
526          return FAILURE;
527  if (CUSTOM_WAVE_DEBUG) 
528    printf("add_per_point_eqn: created new equation (index = %d) (name = \"%s\")\n", per_point_eqn->index, per_point_eqn->param->name);
529  /* Insert the per pixel equation into the preset per pixel database */
530  if (splay_insert(per_point_eqn, &per_point_eqn->index, custom_wave->per_point_eqn_tree) < 0) {
531         free_per_point_eqn(per_point_eqn);
532         return FAILURE;  
533  }
534          
535  /* Done */ 
536  return SUCCESS;
537 }
538
539 per_point_eqn_t * new_per_point_eqn(int index, param_t * param, gen_expr_t * gen_expr) {
540
541         per_point_eqn_t * per_point_eqn;
542         
543         if (param == NULL)
544                 return NULL;
545         if (gen_expr == NULL)
546                 return NULL;
547
548         if ((per_point_eqn = (per_point_eqn_t*)malloc(sizeof(per_point_eqn_t))) == NULL)
549                 return NULL;
550
551       
552         per_point_eqn->index = index;
553         per_point_eqn->gen_expr = gen_expr;
554         per_point_eqn->param = param;
555         return per_point_eqn;   
556 }
557
558
559 void free_per_point_eqn(per_point_eqn_t * per_point_eqn) {
560
561         if (per_point_eqn == NULL)
562                 return;
563         
564         free_gen_expr(per_point_eqn->gen_expr);
565         
566         free(per_point_eqn);
567         
568         return;
569 }
570
571 custom_wave_t * find_custom_wave(int id, preset_t * preset, int create_flag) {
572
573   custom_wave_t * custom_wave = NULL;
574
575   if (preset == NULL)
576     return NULL;
577   
578   if ((custom_wave = splay_find(&id, preset->custom_wave_tree)) == NULL) {
579
580     if (CUSTOM_WAVE_DEBUG) { printf("find_custom_wave: creating custom wave (id = %d)...", id);fflush(stdout);}
581
582     if (create_flag == FALSE) {
583       if (CUSTOM_WAVE_DEBUG) printf("you specified not to (create flag = false), returning null\n");
584        return NULL;
585     }
586
587     if ((custom_wave = new_custom_wave(id)) == NULL) {
588       if (CUSTOM_WAVE_DEBUG) printf("failed...out of memory?\n");
589       return NULL;
590     }
591
592     if  (CUSTOM_WAVE_DEBUG) {printf("success.Inserting..."); fflush(stdout);}
593
594    if (splay_insert(custom_wave, &custom_wave->id, preset->custom_wave_tree) < 0) {
595      if (CUSTOM_WAVE_DEBUG) printf("failed!\n");
596      free_custom_wave(custom_wave);
597      return NULL;
598     }
599  
600    if (CUSTOM_WAVE_DEBUG) printf("done.\n");
601   }
602  
603   return custom_wave;
604 }
605
606 inline void evalCustomWaveInitConditions() {
607   splay_traverse(eval_custom_wave_init_conds, active_preset->custom_wave_tree);
608 }
609
610 inline void eval_custom_wave_init_conds(custom_wave_t * custom_wave) {
611   splay_traverse(eval_init_cond, custom_wave->init_cond_tree);
612   splay_traverse(eval_init_cond, custom_wave->per_frame_init_eqn_tree);
613 }
614
615 /* Interface function. Makes another custom wave the current
616    concern for per frame / point equations */
617 inline custom_wave_t * nextCustomWave() {
618
619   if ((interface_wave = splay_find(&interface_id, active_preset->custom_wave_tree)) == NULL) {
620     interface_id = 0;
621     return NULL;
622   }
623
624   interface_id++;
625
626   /* Evaluate all per frame equations associated with this wave */
627   splay_traverse(eval_per_frame_eqn, interface_wave->per_frame_eqn_tree);
628   return interface_wave;
629 }
630
631
632 inline void evalPerPointEqns() { 
633
634   int x;
635
636   for (x = 0; x < interface_wave->samples; x++)
637     interface_wave->r_mesh[x] = interface_wave->r;
638   for (x = 0; x < interface_wave->samples; x++)
639     interface_wave->g_mesh[x] = interface_wave->g;
640   for (x = 0; x < interface_wave->samples; x++)
641     interface_wave->b_mesh[x] = interface_wave->b;
642   for (x = 0; x < interface_wave->samples; x++)
643     interface_wave->a_mesh[x] = interface_wave->a;
644   for (x = 0; x < interface_wave->samples; x++)
645     interface_wave->x_mesh[x] = interface_wave->x;
646   for (x = 0; x < interface_wave->samples; x++)
647     interface_wave->y_mesh[x] = interface_wave->y;
648
649  
650   /* Evaluate per pixel equations */
651   splay_traverse(evalPerPointEqn, interface_wave->per_point_eqn_tree);
652
653   /* Reset index */
654   mesh_i = -1;
655 }
656
657 /* Evaluates a per point equation for the current custom wave given by interface_wave ptr */
658 inline void evalPerPointEqn(per_point_eqn_t * per_point_eqn) {
659   
660   
661   int samples, size;
662   double * param_matrix;
663   gen_expr_t * eqn_ptr;
664
665   samples = interface_wave->samples;
666   eqn_ptr = per_point_eqn->gen_expr;
667  
668   if (per_point_eqn->param->matrix == NULL) {
669     if ((param_matrix = per_point_eqn->param->matrix = malloc(size = samples*sizeof(double))) == NULL)
670       return;
671     memset(param_matrix, 0, size);
672   }
673   else 
674     param_matrix = (double*)per_point_eqn->param->matrix;
675   
676   for (mesh_i = 0; mesh_i < samples; mesh_i++) {    
677       param_matrix[mesh_i] = eval_gen_expr(eqn_ptr);
678   }
679   
680   /* Now that this parameter has been referenced with a per
681      point equation, we let the evaluator know by setting
682      this flag */
683   per_point_eqn->param->matrix_flag = 1; 
684
685 }
686
687
688 void load_unspecified_init_conds(custom_wave_t * custom_wave) {
689
690   interface_wave = custom_wave;
691   splay_traverse(load_unspec_init_cond, interface_wave->param_tree);
692   interface_wave = NULL;
693  
694 }
695
696 void load_unspec_init_cond(param_t * param) {
697
698   init_cond_t * init_cond;
699   value_t init_val;
700
701   /* Don't count these parameters as initial conditions */
702   if (param->flags & P_FLAG_READONLY)
703     return;
704   if (param->flags & P_FLAG_QVAR)
705     return;
706   if (param->flags & P_FLAG_TVAR)
707     return;
708   if (param->flags & P_FLAG_USERDEF)
709     return;
710
711   /* If initial condition was not defined by the preset file, force a default one
712      with the following code */
713   if ((init_cond = splay_find(param->name, interface_wave->init_cond_tree)) == NULL) {
714     
715     /* Make sure initial condition does not exist in the set of per frame initial equations */
716     if ((init_cond = splay_find(param->name, interface_wave->per_frame_init_eqn_tree)) != NULL)
717       return;
718     
719     if (param->type == P_TYPE_BOOL)
720       init_val.bool_val = 0;
721     
722     else if (param->type == P_TYPE_INT)
723       init_val.int_val = *(int*)param->engine_val;
724
725     else if (param->type == P_TYPE_DOUBLE)
726       init_val.double_val = *(double*)param->engine_val;
727
728     //printf("%s\n", param->name);
729     /* Create new initial condition */
730     if ((init_cond = new_init_cond(param, init_val)) == NULL)
731       return;
732     
733     /* Insert the initial condition into this presets tree */
734     if (splay_insert(init_cond, init_cond->param->name, interface_wave->init_cond_tree) < 0) {
735       free_init_cond(init_cond);
736       return;
737     }
738     
739   }
740  
741 }