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