]> git.sesse.net Git - vlc/blob - modules/visualization/galaktos/custom_shape.c
9a57201715e882020e34e061874d84ae636fd310
[vlc] / modules / visualization / galaktos / custom_shape.c
1 /*****************************************************************************
2  * custom_shape.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 #include <stdio.h>
26
27 #include "common.h"
28 #include "fatal.h"
29
30 #include "param_types.h"
31 #include "param.h"
32
33 #include "expr_types.h"
34 #include "eval.h"
35
36 #include "splaytree_types.h"
37 #include "splaytree.h"
38 #include "tree_types.h"
39
40 #include "per_frame_eqn_types.h"
41 #include "per_frame_eqn.h"
42
43 #include "init_cond_types.h"
44 #include "init_cond.h"
45
46 #include "preset_types.h"
47
48 #include "custom_shape_types.h"
49 #include "custom_shape.h"
50
51 #include "init_cond_types.h"
52 #include "init_cond.h"
53
54 custom_shape_t * interface_shape = NULL;
55 int cwave_interface_id = 0;
56 extern preset_t * active_preset;
57 inline void eval_custom_shape_init_conds(custom_shape_t * custom_shape);
58 void load_unspec_init_cond_shape(param_t * param);
59
60 void destroy_param_db_tree_shape(splaytree_t * tree);
61 void destroy_per_frame_eqn_tree_shape(splaytree_t * tree);
62 void destroy_per_frame_init_eqn_tree_shape(splaytree_t * tree);
63 void destroy_init_cond_tree_shape(splaytree_t * tree);
64
65 custom_shape_t * new_custom_shape(int id) {
66
67   custom_shape_t * custom_shape;
68   param_t * param;
69
70   if ((custom_shape = (custom_shape_t*)malloc(sizeof(custom_shape_t))) == NULL)
71     return NULL;
72
73   custom_shape->id = id;
74   custom_shape->per_frame_count = 0;
75   custom_shape->per_frame_eqn_string_index = 0;
76   custom_shape->per_frame_init_eqn_string_index = 0;
77
78   /* Initialize tree data structures */
79
80   if ((custom_shape->param_tree = 
81        create_splaytree(compare_string, copy_string, free_string)) == NULL) {
82     free_custom_shape(custom_shape);
83     return NULL;
84   }
85
86   if ((custom_shape->per_frame_eqn_tree = 
87        create_splaytree(compare_int, copy_int, free_int)) == NULL) {
88     free_custom_shape(custom_shape);
89     return NULL;
90   }
91
92   if ((custom_shape->init_cond_tree = 
93        create_splaytree(compare_string, copy_string, free_string)) == NULL) {
94     free_custom_shape(custom_shape);
95     return NULL;
96   }
97   
98   if ((custom_shape->per_frame_init_eqn_tree = 
99        create_splaytree(compare_string, copy_string, free_string)) == NULL) {
100     free_custom_shape(custom_shape);
101     return NULL;
102   }
103
104   /* Start: Load custom shape parameters */
105
106   if ((param = new_param_double("r", P_FLAG_NONE, &custom_shape->r, NULL, 1.0, 0.0, .5)) == NULL) {
107     free_custom_shape(custom_shape);
108     return NULL;
109   }
110
111   if (insert_param(param, custom_shape->param_tree) < 0) {
112     free_custom_shape(custom_shape);
113     return NULL;
114   }
115  
116   if ((param = new_param_double("g", P_FLAG_NONE, &custom_shape->g, NULL, 1.0, 0.0, .5)) == NULL){
117     free_custom_shape(custom_shape);
118     return NULL;
119   }
120
121   if (insert_param(param, custom_shape->param_tree) < 0) {
122     free_custom_shape(custom_shape);
123     return NULL;
124   }
125
126   if ((param = new_param_double("b", P_FLAG_NONE, &custom_shape->b, NULL, 1.0, 0.0, .5)) == NULL){
127     free_custom_shape(custom_shape);
128     return NULL;                                       
129   }
130
131   if (insert_param(param, custom_shape->param_tree) < 0) {
132     free_custom_shape(custom_shape);
133     return NULL;
134   }
135
136   if ((param = new_param_double("a", P_FLAG_NONE, &custom_shape->a, NULL, 1.0, 0.0, .5)) == NULL){
137     free_custom_shape(custom_shape);
138     return NULL;
139   }
140
141   if (insert_param(param, custom_shape->param_tree) < 0) {
142     free_custom_shape(custom_shape);
143     return NULL;
144   }
145
146   if ((param = new_param_double("border_r", P_FLAG_NONE, &custom_shape->border_r, NULL, 1.0, 0.0, .5)) == NULL) {
147     free_custom_shape(custom_shape);
148     return NULL;
149   }
150
151   if (insert_param(param, custom_shape->param_tree) < 0) {
152     free_custom_shape(custom_shape);
153     return NULL;
154   }
155  
156   if ((param = new_param_double("border_g", P_FLAG_NONE, &custom_shape->border_g, NULL, 1.0, 0.0, .5)) == NULL){
157     free_custom_shape(custom_shape);
158     return NULL;
159   }
160
161   if (insert_param(param, custom_shape->param_tree) < 0) {
162     free_custom_shape(custom_shape);
163     return NULL;
164   }
165
166   if ((param = new_param_double("border_b", P_FLAG_NONE, &custom_shape->border_b, NULL, 1.0, 0.0, .5)) == NULL){
167     free_custom_shape(custom_shape);
168     return NULL;                                       
169   }
170
171   if (insert_param(param, custom_shape->param_tree) < 0) {
172     free_custom_shape(custom_shape);
173     return NULL;
174   }
175
176   if ((param = new_param_double("border_a", P_FLAG_NONE, &custom_shape->border_a, NULL, 1.0, 0.0, .5)) == NULL){
177     free_custom_shape(custom_shape);
178     return NULL;
179   }
180
181   if (insert_param(param, custom_shape->param_tree) < 0) {
182     free_custom_shape(custom_shape);
183     return NULL;
184   }
185
186   if ((param = new_param_double("r2", P_FLAG_NONE, &custom_shape->r2, NULL, 1.0, 0.0, .5)) == NULL) {
187     free_custom_shape(custom_shape);
188     return NULL;
189   }
190
191   if (insert_param(param, custom_shape->param_tree) < 0) {
192     free_custom_shape(custom_shape);
193     return NULL;
194   }
195  
196   if ((param = new_param_double("g2", P_FLAG_NONE, &custom_shape->g2, NULL, 1.0, 0.0, .5)) == NULL){
197     free_custom_shape(custom_shape);
198     return NULL;
199   }
200
201   if (insert_param(param, custom_shape->param_tree) < 0) {
202     free_custom_shape(custom_shape);
203     return NULL;
204   }
205
206   if ((param = new_param_double("b2", P_FLAG_NONE, &custom_shape->b2, NULL, 1.0, 0.0, .5)) == NULL){
207     free_custom_shape(custom_shape);
208     return NULL;                                       
209   }
210
211   if (insert_param(param, custom_shape->param_tree) < 0) {
212     free_custom_shape(custom_shape);
213     return NULL;
214   }
215
216   if ((param = new_param_double("a2", P_FLAG_NONE, &custom_shape->a2, NULL, 1.0, 0.0, .5)) == NULL){
217     free_custom_shape(custom_shape);
218     return NULL;
219   }
220   
221   if (insert_param(param, custom_shape->param_tree) < 0) {
222     free_custom_shape(custom_shape);
223     return NULL;
224   }
225
226   if ((param = new_param_double("x", P_FLAG_NONE, &custom_shape->x, NULL, 1.0, 0.0, .5)) == NULL) {
227     free_custom_shape(custom_shape);
228     return NULL;
229   }
230
231   if (insert_param(param, custom_shape->param_tree) < 0) {
232     free_custom_shape(custom_shape);
233     return NULL;
234   }
235
236   if ((param = new_param_double("y", P_FLAG_NONE, &custom_shape->y, NULL, 1.0, 0.0, .5)) == NULL) {
237     free_custom_shape(custom_shape);
238     return NULL;
239   }
240
241   if (insert_param(param, custom_shape->param_tree) < 0) {
242     free_custom_shape(custom_shape);
243     return NULL;
244   }
245
246   if ((param = new_param_bool("thickOutline", P_FLAG_NONE, &custom_shape->thickOutline, 1, 0, 0)) == NULL) {
247     free_custom_shape(custom_shape);
248     return NULL;
249   }
250
251   if (insert_param(param, custom_shape->param_tree) < 0) {
252     free_custom_shape(custom_shape);
253     return NULL;
254   }
255
256   if ((param = new_param_bool("enabled", P_FLAG_NONE, &custom_shape->enabled, 1, 0, 0)) == NULL) {
257     free_custom_shape(custom_shape);
258     return NULL;
259   }
260
261   if (insert_param(param, custom_shape->param_tree) < 0) {
262     free_custom_shape(custom_shape);
263     return NULL;
264   }
265
266   if ((param = new_param_int("sides", P_FLAG_NONE, &custom_shape->sides, 100, 3, 3)) == NULL) {
267     free_custom_shape(custom_shape);
268     return NULL;
269   }
270
271   if (insert_param(param, custom_shape->param_tree) < 0) {
272     free_custom_shape(custom_shape);
273     return NULL;
274   }
275
276   if ((param = new_param_bool("additive", P_FLAG_NONE, &custom_shape->additive, 1, 0, 0)) == NULL) {
277     free_custom_shape(custom_shape);
278     return NULL;
279   }
280
281   if (insert_param(param, custom_shape->param_tree) < 0) {
282     free_custom_shape(custom_shape);
283     return NULL;
284   }
285
286   if ((param = new_param_bool("textured", P_FLAG_NONE, &custom_shape->textured, 1, 0, 0)) == NULL) {
287     free_custom_shape(custom_shape);
288     return NULL;
289   }
290
291   if (insert_param(param, custom_shape->param_tree) < 0) {
292     free_custom_shape(custom_shape);
293     return NULL;
294   }
295
296    if ((param = new_param_double("rad", P_FLAG_NONE, &custom_shape->rad, NULL, MAX_DOUBLE_SIZE, 0, 0.0)) == NULL) {
297     free_custom_shape(custom_shape);
298     return NULL;
299   }
300
301    if (insert_param(param, custom_shape->param_tree) < 0) {
302     free_custom_shape(custom_shape);
303     return NULL;
304   }
305
306    if ((param = new_param_double("ang", P_FLAG_NONE, &custom_shape->ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
307     free_custom_shape(custom_shape);
308     return NULL;
309   }
310
311    if (insert_param(param, custom_shape->param_tree) < 0) {
312     free_custom_shape(custom_shape);
313     return NULL;
314   }
315
316    if ((param = new_param_double("tex_zoom", P_FLAG_NONE, &custom_shape->tex_zoom, NULL, MAX_DOUBLE_SIZE, .00000000001, 0.0)) == NULL) {
317     free_custom_shape(custom_shape);
318     return NULL;
319   }
320
321    if (insert_param(param, custom_shape->param_tree) < 0) {
322     free_custom_shape(custom_shape);
323     return NULL;
324   }
325    
326    if ((param = new_param_double("tex_ang", P_FLAG_NONE, &custom_shape->tex_ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
327     free_custom_shape(custom_shape);
328     return NULL;
329   }
330
331    if (insert_param(param, custom_shape->param_tree) < 0) {
332     free_custom_shape(custom_shape);
333     return NULL;
334   }
335    if ((param = new_param_double("t1", P_FLAG_TVAR, &custom_shape->t1, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
336     free_custom_shape(custom_shape);
337     return NULL;
338   }
339
340   if (insert_param(param, custom_shape->param_tree) < 0) {
341     free_custom_shape(custom_shape);
342     return NULL;
343   }
344
345   if ((param = new_param_double("t2", P_FLAG_TVAR, &custom_shape->t2, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
346     free_custom_shape(custom_shape);
347     return NULL;
348   }
349
350   if (insert_param(param, custom_shape->param_tree) < 0) {
351     free_custom_shape(custom_shape);
352     return NULL;
353   }
354
355   if ((param = new_param_double("t3", P_FLAG_TVAR, &custom_shape->t3, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
356     free_custom_shape(custom_shape);
357     return NULL;
358   }
359
360   if (insert_param(param, custom_shape->param_tree) < 0) {
361     free_custom_shape(custom_shape);
362     return NULL;
363   }
364   if ((param = new_param_double("t4", P_FLAG_TVAR, &custom_shape->t4, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
365     free_custom_shape(custom_shape);
366     return NULL;
367   }
368
369   if (insert_param(param, custom_shape->param_tree) < 0) {
370     free_custom_shape(custom_shape);
371     return NULL;
372   }
373   if ((param = new_param_double("t5", P_FLAG_TVAR, &custom_shape->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
374     free_custom_shape(custom_shape);
375     return NULL;
376   }
377  
378   if (insert_param(param, custom_shape->param_tree) < 0) {
379     free_custom_shape(custom_shape);
380     return NULL;
381   }
382   if ((param = new_param_double("t6", P_FLAG_TVAR, &custom_shape->t6, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
383     free_custom_shape(custom_shape);
384     return NULL;
385   }
386
387   if (insert_param(param, custom_shape->param_tree) < 0) {
388     free_custom_shape(custom_shape);
389     return NULL;
390   }
391   if ((param = new_param_double("t7", P_FLAG_TVAR, &custom_shape->t7, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
392     free_custom_shape(custom_shape);
393     return NULL;
394   }
395
396   if (insert_param(param, custom_shape->param_tree) < 0) {
397     free_custom_shape(custom_shape);
398     return NULL;
399   }
400
401   if ((param = new_param_double("t8", P_FLAG_TVAR, &custom_shape->t8, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
402     free_custom_shape(custom_shape);
403     return NULL;
404   }
405
406   if (insert_param(param, custom_shape->param_tree) < 0) {
407     free_custom_shape(custom_shape);
408     return NULL;
409   }
410  
411   /* End of parameter loading. Note that the read only parameters associated
412      with custom shapes (ie, sample) are global variables, and not specific to 
413      the custom shape datastructure. */
414
415
416
417   return custom_shape;
418
419 }
420
421 void destroy_per_frame_init_eqn_tree_shape(splaytree_t * tree) {
422
423   if (!tree)
424     return;
425
426   splay_traverse(free_init_cond, tree);
427   destroy_splaytree(tree);
428
429 }
430
431
432
433 void destroy_init_cond_tree_shape(splaytree_t * tree) {
434
435   if (!tree)
436     return;
437
438   splay_traverse(free_init_cond, tree);
439   destroy_splaytree(tree);
440
441 }
442
443 void destroy_per_frame_eqn_tree_shape(splaytree_t * tree) {
444
445
446   if (!tree)
447     return;
448
449   splay_traverse(free_per_frame_eqn, tree);
450   destroy_splaytree(tree);
451
452 }
453
454
455 void destroy_param_db_tree_shape(splaytree_t * tree) {
456
457   if (!tree)
458     return;
459
460   splay_traverse(free_param, tree);
461   destroy_splaytree(tree);
462
463 }
464
465 /* Frees a custom shape form object */
466 void free_custom_shape(custom_shape_t * custom_shape) {
467
468   if (custom_shape == NULL)
469     return;
470
471   if (custom_shape->param_tree == NULL)
472     return;
473
474   destroy_per_frame_eqn_tree_shape(custom_shape->per_frame_eqn_tree);
475   destroy_init_cond_tree_shape(custom_shape->init_cond_tree);
476   destroy_param_db_tree_shape(custom_shape->param_tree);
477   destroy_per_frame_init_eqn_tree_shape(custom_shape->per_frame_init_eqn_tree);
478   
479   free(custom_shape);
480
481   return;
482
483 }
484
485
486 custom_shape_t * find_custom_shape(int id, preset_t * preset, int create_flag) {
487
488   custom_shape_t * custom_shape = NULL;
489
490   if (preset == NULL)
491     return NULL;
492   
493   if ((custom_shape = splay_find(&id, preset->custom_shape_tree)) == NULL) {
494     
495     if (CUSTOM_SHAPE_DEBUG) { printf("find_custom_shape: creating custom shape (id = %d)...", id);fflush(stdout);}
496     
497     if (create_flag == FALSE) {
498       if (CUSTOM_SHAPE_DEBUG) printf("you specified not to (create flag = false), returning null\n");
499       return NULL;
500     }
501     
502     if ((custom_shape = new_custom_shape(id)) == NULL) {
503       if (CUSTOM_SHAPE_DEBUG) printf("failed...out of memory?\n");
504       return NULL;
505     }
506     
507     if (CUSTOM_SHAPE_DEBUG) { printf("success.Inserting..."); fflush(stdout);}
508     
509     if (splay_insert(custom_shape, &custom_shape->id, preset->custom_shape_tree) < 0) {
510       if (CUSTOM_SHAPE_DEBUG) printf("failed, probably a duplicated!!\n");
511       free_custom_shape(custom_shape);
512       return NULL;
513     }
514     
515     if (CUSTOM_SHAPE_DEBUG) printf("done.\n");
516   }
517   
518   return custom_shape;
519 }
520
521 inline void evalCustomShapeInitConditions() {
522   splay_traverse(eval_custom_shape_init_conds, active_preset->custom_shape_tree);
523
524 }
525
526 inline void eval_custom_shape_init_conds(custom_shape_t * custom_shape) {
527   splay_traverse(eval_init_cond, custom_shape->init_cond_tree);
528   splay_traverse(eval_init_cond, custom_shape->per_frame_init_eqn_tree);
529 }
530
531
532 void load_unspecified_init_conds_shape(custom_shape_t * custom_shape) {
533
534   interface_shape = custom_shape;
535   splay_traverse(load_unspec_init_cond_shape, interface_shape->param_tree);
536   interface_shape = NULL;
537  
538 }
539
540 void load_unspec_init_cond_shape(param_t * param) {
541
542   init_cond_t * init_cond;
543   value_t init_val;
544
545   /* Don't count read only parameters as initial conditions */
546   if (param->flags & P_FLAG_READONLY)
547     return;
548  if (param->flags & P_FLAG_QVAR)
549     return;
550  if (param->flags & P_FLAG_TVAR)
551     return;
552  if (param->flags & P_FLAG_USERDEF)
553     return;
554
555   /* If initial condition was not defined by the preset file, force a default one
556      with the following code */
557   if ((init_cond = splay_find(param->name, interface_shape->init_cond_tree)) == NULL) {
558     
559     /* Make sure initial condition does not exist in the set of per frame initial equations */
560     if ((init_cond = splay_find(param->name, interface_shape->per_frame_init_eqn_tree)) != NULL)
561       return;
562     
563     if (param->type == P_TYPE_BOOL)
564       init_val.bool_val = 0;
565     
566     else if (param->type == P_TYPE_INT)
567       init_val.int_val = *(int*)param->engine_val;
568
569     else if (param->type == P_TYPE_DOUBLE)
570       init_val.double_val = *(double*)param->engine_val;
571
572     //printf("%s\n", param->name);
573     /* Create new initial condition */
574     if ((init_cond = new_init_cond(param, init_val)) == NULL)
575       return;
576     
577     /* Insert the initial condition into this presets tree */
578     if (splay_insert(init_cond, init_cond->param->name, interface_shape->init_cond_tree) < 0) {
579       free_init_cond(init_cond);
580       return;
581     }
582     
583   }
584  
585 }
586
587
588 /* Interface function. Makes another custom shape the current
589    concern for per frame / point equations */
590 inline custom_shape_t * nextCustomShape() {
591
592   if ((interface_shape = splay_find(&cwave_interface_id, active_preset->custom_shape_tree)) == NULL) {
593     cwave_interface_id = 0;
594     return NULL;
595   }
596
597   cwave_interface_id++;
598
599   /* Evaluate all per frame equations associated with this shape */
600   splay_traverse(eval_per_frame_eqn, interface_shape->per_frame_eqn_tree);
601   return interface_shape;
602 }