1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004 VideoLAN
7 * Authors: Cyril Deguet <asmax@videolan.org>
8 * code from projectM http://xmms-projectm.sourceforge.net
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.
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.
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 *****************************************************************************/
34 #include "param_types.h"
37 #include "expr_types.h"
40 #include "splaytree_types.h"
41 #include "splaytree.h"
42 #include "tree_types.h"
44 #include "per_frame_eqn_types.h"
45 #include "per_frame_eqn.h"
47 #include "init_cond_types.h"
48 #include "init_cond.h"
50 #include "preset_types.h"
52 #include "custom_wave_types.h"
53 #include "custom_wave.h"
55 #include "init_cond_types.h"
56 #include "init_cond.h"
58 #include "engine_vars.h"
59 #define MAX_SAMPLE_SIZE 4096
63 custom_wave_t * interface_wave = NULL;
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);
75 custom_wave_t * new_custom_wave(int id) {
77 custom_wave_t * custom_wave;
80 if ((custom_wave = (custom_wave_t*)malloc(sizeof(custom_wave_t))) == NULL)
84 custom_wave->per_frame_count = 0;
86 custom_wave->samples = 512;
87 custom_wave->bSpectrum = 0;
88 custom_wave->enabled = 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;
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));
109 /* Initialize tree data structures */
111 if ((custom_wave->param_tree =
112 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
113 free_custom_wave(custom_wave);
117 if ((custom_wave->per_point_eqn_tree =
118 create_splaytree(compare_int, copy_int, free_int)) == NULL) {
119 free_custom_wave(custom_wave);
123 if ((custom_wave->per_frame_eqn_tree =
124 create_splaytree(compare_int, copy_int, free_int)) == NULL) {
125 free_custom_wave(custom_wave);
129 if ((custom_wave->init_cond_tree =
130 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
131 free_custom_wave(custom_wave);
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);
142 /* Start: Load custom wave parameters */
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);
149 if (insert_param(param, custom_wave->param_tree) < 0) {
150 free_custom_wave(custom_wave);
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);
159 if (insert_param(param, custom_wave->param_tree) < 0) {
160 free_custom_wave(custom_wave);
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);
169 if (insert_param(param, custom_wave->param_tree) < 0) {
170 free_custom_wave(custom_wave);
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);
179 if (insert_param(param, custom_wave->param_tree) < 0) {
180 free_custom_wave(custom_wave);
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);
189 if (insert_param(param, custom_wave->param_tree) < 0) {
190 free_custom_wave(custom_wave);
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);
199 if (insert_param(param, custom_wave->param_tree) < 0) {
200 free_custom_wave(custom_wave);
204 if ((param = new_param_bool("enabled", P_FLAG_NONE, &custom_wave->enabled, 1, 0, 0)) == NULL) {
205 free_custom_wave(custom_wave);
209 if (insert_param(param, custom_wave->param_tree) < 0) {
210 free_custom_wave(custom_wave);
214 if ((param = new_param_int("sep", P_FLAG_NONE, &custom_wave->sep, 100, -100, 0)) == NULL) {
215 free_custom_wave(custom_wave);
219 if (insert_param(param, custom_wave->param_tree) < 0) {
220 free_custom_wave(custom_wave);
224 if ((param = new_param_bool("bSpectrum", P_FLAG_NONE, &custom_wave->bSpectrum, 1, 0, 0)) == NULL) {
225 free_custom_wave(custom_wave);
229 if (insert_param(param, custom_wave->param_tree) < 0) {
230 free_custom_wave(custom_wave);
234 if ((param = new_param_bool("bDrawThick", P_FLAG_NONE, &custom_wave->bDrawThick, 1, 0, 0)) == NULL) {
235 free_custom_wave(custom_wave);
239 if (insert_param(param, custom_wave->param_tree) < 0) {
240 free_custom_wave(custom_wave);
244 if ((param = new_param_bool("bUseDots", P_FLAG_NONE, &custom_wave->bUseDots, 1, 0, 0)) == NULL) {
245 free_custom_wave(custom_wave);
249 if (insert_param(param, custom_wave->param_tree) < 0) {
250 free_custom_wave(custom_wave);
254 if ((param = new_param_bool("bAdditive", P_FLAG_NONE, &custom_wave->bAdditive, 1, 0, 0)) == NULL) {
255 free_custom_wave(custom_wave);
259 if (insert_param(param, custom_wave->param_tree) < 0) {
260 free_custom_wave(custom_wave);
264 if ((param = new_param_int("samples", P_FLAG_NONE, &custom_wave->samples, 2048, 1, 512)) == NULL) {
265 free_custom_wave(custom_wave);
269 if (insert_param(param, custom_wave->param_tree) < 0) {
270 free_custom_wave(custom_wave);
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);
280 if (insert_param(param, custom_wave->param_tree) < 0) {
281 printf("failed to insert sample\n");
282 free_custom_wave(custom_wave);
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);
291 if (insert_param(param, custom_wave->param_tree) < 0) {
292 free_custom_wave(custom_wave);
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);
301 if (insert_param(param, custom_wave->param_tree) < 0) {
302 free_custom_wave(custom_wave);
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);
311 if (insert_param(param, custom_wave->param_tree) < 0) {
312 free_custom_wave(custom_wave);
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);
321 if (insert_param(param, custom_wave->param_tree) < 0) {
322 free_custom_wave(custom_wave);
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);
331 if (insert_param(param, custom_wave->param_tree) < 0) {
332 free_custom_wave(custom_wave);
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);
341 if (insert_param(param, custom_wave->param_tree) < 0) {
342 free_custom_wave(custom_wave);
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);
351 if (insert_param(param, custom_wave->param_tree) < 0) {
352 free_custom_wave(custom_wave);
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);
360 if (insert_param(param, custom_wave->param_tree) < 0) {
361 free_custom_wave(custom_wave);
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);
369 if (insert_param(param, custom_wave->param_tree) < 0) {
370 free_custom_wave(custom_wave);
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);
378 if (insert_param(param, custom_wave->param_tree) < 0) {
379 free_custom_wave(custom_wave);
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);
387 if (insert_param(param, custom_wave->param_tree) < 0) {
388 free_custom_wave(custom_wave);
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);
397 if (insert_param(param, custom_wave->param_tree) < 0) {
398 free_custom_wave(custom_wave);
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. */
411 void destroy_per_frame_init_eqn_tree(splaytree_t * tree) {
416 splay_traverse(free_init_cond, tree);
417 destroy_splaytree(tree);
422 void destroy_per_point_eqn_tree(splaytree_t * tree) {
427 splay_traverse(free_per_point_eqn, tree);
428 destroy_splaytree(tree);
432 void destroy_init_cond_tree(splaytree_t * tree) {
437 splay_traverse(free_init_cond, tree);
438 destroy_splaytree(tree);
442 void destroy_per_frame_eqn_tree(splaytree_t * tree) {
448 splay_traverse(free_per_frame_eqn, tree);
449 destroy_splaytree(tree);
454 void destroy_param_db_tree(splaytree_t * tree) {
459 splay_traverse(free_param, tree);
460 destroy_splaytree(tree);
464 /* Frees a custom wave form object */
465 void free_custom_wave(custom_wave_t * custom_wave) {
467 if (custom_wave == NULL)
470 if (custom_wave->param_tree == NULL)
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);
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);
497 int add_per_point_eqn(char * name, gen_expr_t * gen_expr, custom_wave_t * custom_wave) {
499 per_point_eqn_t * per_point_eqn;
501 param_t * param = NULL;
503 /* Argument checks */
504 if (custom_wave == NULL)
506 if (gen_expr == NULL)
511 if (CUSTOM_WAVE_DEBUG) printf("add_per_point_eqn: per pixel equation (name = \"%s\")\n", name);
513 /* Search for the parameter so we know what matrix the per pixel equation is referencing */
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");
521 /* Find most largest index in the splaytree */
522 if ((per_point_eqn = splay_find_max(custom_wave->per_point_eqn_tree)) == NULL)
525 index = per_point_eqn->index+1;
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)
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);
542 per_point_eqn_t * new_per_point_eqn(int index, param_t * param, gen_expr_t * gen_expr) {
544 per_point_eqn_t * per_point_eqn;
548 if (gen_expr == NULL)
551 if ((per_point_eqn = (per_point_eqn_t*)malloc(sizeof(per_point_eqn_t))) == NULL)
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;
562 void free_per_point_eqn(per_point_eqn_t * per_point_eqn) {
564 if (per_point_eqn == NULL)
567 free_gen_expr(per_point_eqn->gen_expr);
574 custom_wave_t * find_custom_wave(int id, preset_t * preset, int create_flag) {
576 custom_wave_t * custom_wave = NULL;
581 if ((custom_wave = splay_find(&id, preset->custom_wave_tree)) == NULL) {
583 if (CUSTOM_WAVE_DEBUG) { printf("find_custom_wave: creating custom wave (id = %d)...", id);fflush(stdout);}
585 if (create_flag == FALSE) {
586 if (CUSTOM_WAVE_DEBUG) printf("you specified not to (create flag = false), returning null\n");
590 if ((custom_wave = new_custom_wave(id)) == NULL) {
591 if (CUSTOM_WAVE_DEBUG) printf("failed...out of memory?\n");
595 if (CUSTOM_WAVE_DEBUG) {printf("success.Inserting..."); fflush(stdout);}
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);
603 if (CUSTOM_WAVE_DEBUG) printf("done.\n");
609 inline void evalCustomWaveInitConditions() {
610 splay_traverse(eval_custom_wave_init_conds, active_preset->custom_wave_tree);
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);
618 /* Interface function. Makes another custom wave the current
619 concern for per frame / point equations */
620 inline custom_wave_t * nextCustomWave() {
622 if ((interface_wave = splay_find(&interface_id, active_preset->custom_wave_tree)) == NULL) {
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;
635 inline void evalPerPointEqns() {
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;
653 /* Evaluate per pixel equations */
654 splay_traverse(evalPerPointEqn, interface_wave->per_point_eqn_tree);
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) {
665 double * param_matrix;
666 gen_expr_t * eqn_ptr;
668 samples = interface_wave->samples;
669 eqn_ptr = per_point_eqn->gen_expr;
671 if (per_point_eqn->param->matrix == NULL) {
672 if ((param_matrix = per_point_eqn->param->matrix = malloc(size = samples*sizeof(double))) == NULL)
674 memset(param_matrix, 0, size);
677 param_matrix = (double*)per_point_eqn->param->matrix;
679 for (mesh_i = 0; mesh_i < samples; mesh_i++) {
680 param_matrix[mesh_i] = eval_gen_expr(eqn_ptr);
683 /* Now that this parameter has been referenced with a per
684 point equation, we let the evaluator know by setting
686 per_point_eqn->param->matrix_flag = 1;
691 void load_unspecified_init_conds(custom_wave_t * custom_wave) {
693 interface_wave = custom_wave;
694 splay_traverse(load_unspec_init_cond, interface_wave->param_tree);
695 interface_wave = NULL;
699 void load_unspec_init_cond(param_t * param) {
701 init_cond_t * init_cond;
704 /* Don't count these parameters as initial conditions */
705 if (param->flags & P_FLAG_READONLY)
707 if (param->flags & P_FLAG_QVAR)
709 if (param->flags & P_FLAG_TVAR)
711 if (param->flags & P_FLAG_USERDEF)
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) {
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)
722 if (param->type == P_TYPE_BOOL)
723 init_val.bool_val = 0;
725 else if (param->type == P_TYPE_INT)
726 init_val.int_val = *(int*)param->engine_val;
728 else if (param->type == P_TYPE_DOUBLE)
729 init_val.double_val = *(double*)param->engine_val;
731 //printf("%s\n", param->name);
732 /* Create new initial condition */
733 if ((init_cond = new_init_cond(param, init_val)) == NULL)
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);