1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004 the VideoLAN team
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
30 #include "param_types.h"
33 #include "expr_types.h"
36 #include "splaytree_types.h"
37 #include "splaytree.h"
38 #include "tree_types.h"
40 #include "per_frame_eqn_types.h"
41 #include "per_frame_eqn.h"
43 #include "init_cond_types.h"
44 #include "init_cond.h"
46 #include "preset_types.h"
48 #include "custom_wave_types.h"
49 #include "custom_wave.h"
51 #include "init_cond_types.h"
52 #include "init_cond.h"
54 #include "engine_vars.h"
55 #define MAX_SAMPLE_SIZE 4096
59 custom_wave_t * interface_wave = NULL;
61 extern preset_t * active_preset;
62 inline void eval_custom_wave_init_conds(custom_wave_t * custom_wave);
63 void load_unspec_init_cond(param_t * param);
64 void destroy_per_point_eqn_tree(splaytree_t * tree);
65 void destroy_param_db_tree(splaytree_t * tree);
66 void destroy_per_frame_eqn_tree(splaytree_t * tree);
67 void destroy_per_frame_init_eqn_tree(splaytree_t * tree);
68 void destroy_init_cond_tree(splaytree_t * tree);
69 inline void evalPerPointEqn(per_point_eqn_t * per_point_eqn);
71 custom_wave_t * new_custom_wave(int id) {
73 custom_wave_t * custom_wave;
76 if ((custom_wave = (custom_wave_t*)malloc(sizeof(custom_wave_t))) == NULL)
80 custom_wave->per_frame_count = 0;
82 custom_wave->samples = 512;
83 custom_wave->bSpectrum = 0;
84 custom_wave->enabled = 1;
86 custom_wave->smoothing = 0.0;
87 custom_wave->bUseDots = 0;
88 custom_wave->bAdditive = 0;
89 custom_wave->r = custom_wave->g = custom_wave->b = custom_wave->a = 0.0;
90 custom_wave->scaling = 1.0;
91 custom_wave->per_frame_eqn_string_index = 0;
92 custom_wave->per_frame_init_eqn_string_index = 0;
93 custom_wave->per_point_eqn_string_index = 0;
95 custom_wave->r_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
96 custom_wave->g_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
97 custom_wave->b_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
98 custom_wave->a_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
99 custom_wave->x_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
100 custom_wave->y_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
101 custom_wave->value1 = malloc(MAX_SAMPLE_SIZE*sizeof(double));
102 custom_wave->value2 = malloc(MAX_SAMPLE_SIZE*sizeof(double));
103 custom_wave->sample_mesh = malloc(MAX_SAMPLE_SIZE*sizeof(double));
105 /* Initialize tree data structures */
107 if ((custom_wave->param_tree =
108 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
109 free_custom_wave(custom_wave);
113 if ((custom_wave->per_point_eqn_tree =
114 create_splaytree(compare_int, copy_int, free_int)) == NULL) {
115 free_custom_wave(custom_wave);
119 if ((custom_wave->per_frame_eqn_tree =
120 create_splaytree(compare_int, copy_int, free_int)) == NULL) {
121 free_custom_wave(custom_wave);
125 if ((custom_wave->init_cond_tree =
126 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
127 free_custom_wave(custom_wave);
131 if ((custom_wave->per_frame_init_eqn_tree =
132 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
133 free_custom_wave(custom_wave);
138 /* Start: Load custom wave parameters */
140 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) {
141 free_custom_wave(custom_wave);
145 if (insert_param(param, custom_wave->param_tree) < 0) {
146 free_custom_wave(custom_wave);
150 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){
151 free_custom_wave(custom_wave);
155 if (insert_param(param, custom_wave->param_tree) < 0) {
156 free_custom_wave(custom_wave);
160 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){
161 free_custom_wave(custom_wave);
165 if (insert_param(param, custom_wave->param_tree) < 0) {
166 free_custom_wave(custom_wave);
170 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){
171 free_custom_wave(custom_wave);
175 if (insert_param(param, custom_wave->param_tree) < 0) {
176 free_custom_wave(custom_wave);
180 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) {
181 free_custom_wave(custom_wave);
185 if (insert_param(param, custom_wave->param_tree) < 0) {
186 free_custom_wave(custom_wave);
190 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) {
191 free_custom_wave(custom_wave);
195 if (insert_param(param, custom_wave->param_tree) < 0) {
196 free_custom_wave(custom_wave);
200 if ((param = new_param_bool("enabled", P_FLAG_NONE, &custom_wave->enabled, 1, 0, 0)) == NULL) {
201 free_custom_wave(custom_wave);
205 if (insert_param(param, custom_wave->param_tree) < 0) {
206 free_custom_wave(custom_wave);
210 if ((param = new_param_int("sep", P_FLAG_NONE, &custom_wave->sep, 100, -100, 0)) == NULL) {
211 free_custom_wave(custom_wave);
215 if (insert_param(param, custom_wave->param_tree) < 0) {
216 free_custom_wave(custom_wave);
220 if ((param = new_param_bool("bSpectrum", P_FLAG_NONE, &custom_wave->bSpectrum, 1, 0, 0)) == NULL) {
221 free_custom_wave(custom_wave);
225 if (insert_param(param, custom_wave->param_tree) < 0) {
226 free_custom_wave(custom_wave);
230 if ((param = new_param_bool("bDrawThick", P_FLAG_NONE, &custom_wave->bDrawThick, 1, 0, 0)) == NULL) {
231 free_custom_wave(custom_wave);
235 if (insert_param(param, custom_wave->param_tree) < 0) {
236 free_custom_wave(custom_wave);
240 if ((param = new_param_bool("bUseDots", P_FLAG_NONE, &custom_wave->bUseDots, 1, 0, 0)) == NULL) {
241 free_custom_wave(custom_wave);
245 if (insert_param(param, custom_wave->param_tree) < 0) {
246 free_custom_wave(custom_wave);
250 if ((param = new_param_bool("bAdditive", P_FLAG_NONE, &custom_wave->bAdditive, 1, 0, 0)) == NULL) {
251 free_custom_wave(custom_wave);
255 if (insert_param(param, custom_wave->param_tree) < 0) {
256 free_custom_wave(custom_wave);
260 if ((param = new_param_int("samples", P_FLAG_NONE, &custom_wave->samples, 2048, 1, 512)) == NULL) {
261 free_custom_wave(custom_wave);
265 if (insert_param(param, custom_wave->param_tree) < 0) {
266 free_custom_wave(custom_wave);
270 if ((param = new_param_double("sample", P_FLAG_READONLY | P_FLAG_DONT_FREE_MATRIX | P_FLAG_ALWAYS_MATRIX | P_FLAG_PER_POINT,
271 &custom_wave->sample, custom_wave->sample_mesh, 1.0, 0.0, 0.0)) == NULL) {
272 free_custom_wave(custom_wave);
276 if (insert_param(param, custom_wave->param_tree) < 0) {
277 printf("failed to insert sample\n");
278 free_custom_wave(custom_wave);
282 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) {
283 free_custom_wave(custom_wave);
287 if (insert_param(param, custom_wave->param_tree) < 0) {
288 free_custom_wave(custom_wave);
292 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) {
293 free_custom_wave(custom_wave);
297 if (insert_param(param, custom_wave->param_tree) < 0) {
298 free_custom_wave(custom_wave);
302 if ((param = new_param_double("smoothing", P_FLAG_NONE, &custom_wave->smoothing, NULL, 1.0, 0.0, 0.0)) == NULL) {
303 free_custom_wave(custom_wave);
307 if (insert_param(param, custom_wave->param_tree) < 0) {
308 free_custom_wave(custom_wave);
312 if ((param = new_param_double("scaling", P_FLAG_NONE, &custom_wave->scaling, NULL, MAX_DOUBLE_SIZE, 0.0, 1.0)) == NULL) {
313 free_custom_wave(custom_wave);
317 if (insert_param(param, custom_wave->param_tree) < 0) {
318 free_custom_wave(custom_wave);
322 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) {
323 free_custom_wave(custom_wave);
327 if (insert_param(param, custom_wave->param_tree) < 0) {
328 free_custom_wave(custom_wave);
332 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) {
333 free_custom_wave(custom_wave);
337 if (insert_param(param, custom_wave->param_tree) < 0) {
338 free_custom_wave(custom_wave);
342 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) {
343 free_custom_wave(custom_wave);
347 if (insert_param(param, custom_wave->param_tree) < 0) {
348 free_custom_wave(custom_wave);
351 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) {
352 free_custom_wave(custom_wave);
356 if (insert_param(param, custom_wave->param_tree) < 0) {
357 free_custom_wave(custom_wave);
360 if ((param = new_param_double("t5", P_FLAG_TVAR, &custom_wave->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
361 free_custom_wave(custom_wave);
365 if (insert_param(param, custom_wave->param_tree) < 0) {
366 free_custom_wave(custom_wave);
369 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) {
370 free_custom_wave(custom_wave);
374 if (insert_param(param, custom_wave->param_tree) < 0) {
375 free_custom_wave(custom_wave);
378 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) {
379 free_custom_wave(custom_wave);
383 if (insert_param(param, custom_wave->param_tree) < 0) {
384 free_custom_wave(custom_wave);
388 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) {
389 free_custom_wave(custom_wave);
393 if (insert_param(param, custom_wave->param_tree) < 0) {
394 free_custom_wave(custom_wave);
398 /* End of parameter loading. Note that the read only parameters associated
399 with custom waves (ie, sample) are global variables, and not specific to
400 the custom wave datastructure. */
407 void destroy_per_frame_init_eqn_tree(splaytree_t * tree) {
412 splay_traverse(free_init_cond, tree);
413 destroy_splaytree(tree);
418 void destroy_per_point_eqn_tree(splaytree_t * tree) {
423 splay_traverse(free_per_point_eqn, tree);
424 destroy_splaytree(tree);
428 void destroy_init_cond_tree(splaytree_t * tree) {
433 splay_traverse(free_init_cond, tree);
434 destroy_splaytree(tree);
438 void destroy_per_frame_eqn_tree(splaytree_t * tree) {
444 splay_traverse(free_per_frame_eqn, tree);
445 destroy_splaytree(tree);
450 void destroy_param_db_tree(splaytree_t * tree) {
455 splay_traverse(free_param, tree);
456 destroy_splaytree(tree);
460 /* Frees a custom wave form object */
461 void free_custom_wave(custom_wave_t * custom_wave) {
463 if (custom_wave == NULL)
466 if (custom_wave->param_tree == NULL)
469 destroy_per_point_eqn_tree(custom_wave->per_point_eqn_tree);
470 destroy_per_frame_eqn_tree(custom_wave->per_frame_eqn_tree);
471 destroy_init_cond_tree(custom_wave->init_cond_tree);
472 destroy_param_db_tree(custom_wave->param_tree);
473 destroy_per_frame_init_eqn_tree(custom_wave->per_frame_init_eqn_tree);
475 free(custom_wave->r_mesh);
476 free(custom_wave->g_mesh);
477 free(custom_wave->b_mesh);
478 free(custom_wave->a_mesh);
479 free(custom_wave->x_mesh);
480 free(custom_wave->y_mesh);
481 free(custom_wave->value1);
482 free(custom_wave->value2);
483 free(custom_wave->sample_mesh);
493 int add_per_point_eqn(char * name, gen_expr_t * gen_expr, custom_wave_t * custom_wave) {
495 per_point_eqn_t * per_point_eqn;
497 param_t * param = NULL;
499 /* Argument checks */
500 if (custom_wave == NULL)
502 if (gen_expr == NULL)
507 if (CUSTOM_WAVE_DEBUG) printf("add_per_point_eqn: per pixel equation (name = \"%s\")\n", name);
509 /* Search for the parameter so we know what matrix the per pixel equation is referencing */
511 if ((param = find_param_db(name, custom_wave->param_tree, TRUE)) == NULL) {
512 if (CUSTOM_WAVE_DEBUG) printf("add_per_point_eqn: failed to allocate a new parameter!\n");
517 /* Find most largest index in the splaytree */
518 if ((per_point_eqn = splay_find_max(custom_wave->per_point_eqn_tree)) == NULL)
521 index = per_point_eqn->index+1;
523 /* Create the per pixel equation given the index, parameter, and general expression */
524 if ((per_point_eqn = new_per_point_eqn(index, param, gen_expr)) == NULL)
526 if (CUSTOM_WAVE_DEBUG)
527 printf("add_per_point_eqn: created new equation (index = %d) (name = \"%s\")\n", per_point_eqn->index, per_point_eqn->param->name);
528 /* Insert the per pixel equation into the preset per pixel database */
529 if (splay_insert(per_point_eqn, &per_point_eqn->index, custom_wave->per_point_eqn_tree) < 0) {
530 free_per_point_eqn(per_point_eqn);
538 per_point_eqn_t * new_per_point_eqn(int index, param_t * param, gen_expr_t * gen_expr) {
540 per_point_eqn_t * per_point_eqn;
544 if (gen_expr == NULL)
547 if ((per_point_eqn = (per_point_eqn_t*)malloc(sizeof(per_point_eqn_t))) == NULL)
551 per_point_eqn->index = index;
552 per_point_eqn->gen_expr = gen_expr;
553 per_point_eqn->param = param;
554 return per_point_eqn;
558 void free_per_point_eqn(per_point_eqn_t * per_point_eqn) {
560 if (per_point_eqn == NULL)
563 free_gen_expr(per_point_eqn->gen_expr);
570 custom_wave_t * find_custom_wave(int id, preset_t * preset, int create_flag) {
572 custom_wave_t * custom_wave = NULL;
577 if ((custom_wave = splay_find(&id, preset->custom_wave_tree)) == NULL) {
579 if (CUSTOM_WAVE_DEBUG) { printf("find_custom_wave: creating custom wave (id = %d)...", id);fflush(stdout);}
581 if (create_flag == FALSE) {
582 if (CUSTOM_WAVE_DEBUG) printf("you specified not to (create flag = false), returning null\n");
586 if ((custom_wave = new_custom_wave(id)) == NULL) {
587 if (CUSTOM_WAVE_DEBUG) printf("failed...out of memory?\n");
591 if (CUSTOM_WAVE_DEBUG) {printf("success.Inserting..."); fflush(stdout);}
593 if (splay_insert(custom_wave, &custom_wave->id, preset->custom_wave_tree) < 0) {
594 if (CUSTOM_WAVE_DEBUG) printf("failed!\n");
595 free_custom_wave(custom_wave);
599 if (CUSTOM_WAVE_DEBUG) printf("done.\n");
605 inline void evalCustomWaveInitConditions() {
606 splay_traverse(eval_custom_wave_init_conds, active_preset->custom_wave_tree);
609 inline void eval_custom_wave_init_conds(custom_wave_t * custom_wave) {
610 splay_traverse(eval_init_cond, custom_wave->init_cond_tree);
611 splay_traverse(eval_init_cond, custom_wave->per_frame_init_eqn_tree);
614 /* Interface function. Makes another custom wave the current
615 concern for per frame / point equations */
616 inline custom_wave_t * nextCustomWave() {
618 if ((interface_wave = splay_find(&interface_id, active_preset->custom_wave_tree)) == NULL) {
625 /* Evaluate all per frame equations associated with this wave */
626 splay_traverse(eval_per_frame_eqn, interface_wave->per_frame_eqn_tree);
627 return interface_wave;
631 inline void evalPerPointEqns() {
635 for (x = 0; x < interface_wave->samples; x++)
636 interface_wave->r_mesh[x] = interface_wave->r;
637 for (x = 0; x < interface_wave->samples; x++)
638 interface_wave->g_mesh[x] = interface_wave->g;
639 for (x = 0; x < interface_wave->samples; x++)
640 interface_wave->b_mesh[x] = interface_wave->b;
641 for (x = 0; x < interface_wave->samples; x++)
642 interface_wave->a_mesh[x] = interface_wave->a;
643 for (x = 0; x < interface_wave->samples; x++)
644 interface_wave->x_mesh[x] = interface_wave->x;
645 for (x = 0; x < interface_wave->samples; x++)
646 interface_wave->y_mesh[x] = interface_wave->y;
649 /* Evaluate per pixel equations */
650 splay_traverse(evalPerPointEqn, interface_wave->per_point_eqn_tree);
656 /* Evaluates a per point equation for the current custom wave given by interface_wave ptr */
657 inline void evalPerPointEqn(per_point_eqn_t * per_point_eqn) {
661 double * param_matrix;
662 gen_expr_t * eqn_ptr;
664 samples = interface_wave->samples;
665 eqn_ptr = per_point_eqn->gen_expr;
667 if (per_point_eqn->param->matrix == NULL) {
668 if ((param_matrix = per_point_eqn->param->matrix = malloc(size = samples*sizeof(double))) == NULL)
670 memset(param_matrix, 0, size);
673 param_matrix = (double*)per_point_eqn->param->matrix;
675 for (mesh_i = 0; mesh_i < samples; mesh_i++) {
676 param_matrix[mesh_i] = eval_gen_expr(eqn_ptr);
679 /* Now that this parameter has been referenced with a per
680 point equation, we let the evaluator know by setting
682 per_point_eqn->param->matrix_flag = 1;
687 void load_unspecified_init_conds(custom_wave_t * custom_wave) {
689 interface_wave = custom_wave;
690 splay_traverse(load_unspec_init_cond, interface_wave->param_tree);
691 interface_wave = NULL;
695 void load_unspec_init_cond(param_t * param) {
697 init_cond_t * init_cond;
700 /* Don't count these parameters as initial conditions */
701 if (param->flags & P_FLAG_READONLY)
703 if (param->flags & P_FLAG_QVAR)
705 if (param->flags & P_FLAG_TVAR)
707 if (param->flags & P_FLAG_USERDEF)
710 /* If initial condition was not defined by the preset file, force a default one
711 with the following code */
712 if ((init_cond = splay_find(param->name, interface_wave->init_cond_tree)) == NULL) {
714 /* Make sure initial condition does not exist in the set of per frame initial equations */
715 if ((init_cond = splay_find(param->name, interface_wave->per_frame_init_eqn_tree)) != NULL)
718 if (param->type == P_TYPE_BOOL)
719 init_val.bool_val = 0;
721 else if (param->type == P_TYPE_INT)
722 init_val.int_val = *(int*)param->engine_val;
724 else if (param->type == P_TYPE_DOUBLE)
725 init_val.double_val = *(double*)param->engine_val;
727 //printf("%s\n", param->name);
728 /* Create new initial condition */
729 if ((init_cond = new_init_cond(param, init_val)) == NULL)
732 /* Insert the initial condition into this presets tree */
733 if (splay_insert(init_cond, init_cond->param->name, interface_wave->init_cond_tree) < 0) {
734 free_init_cond(init_cond);