Files
projectm/src/projectM-engine/Preset.cpp
w1z7ard 0e6df2a168 import of 1.0 branch
git-svn-id: https://projectm.svn.sourceforge.net/svnroot/projectm/trunk@152 6778bc44-b910-0410-a7a0-be141de4315d
2007-06-13 02:34:15 +00:00

670 lines
19 KiB
C++
Executable File

/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef WIN32
#include "win32-dirent.h"
#else
#include <dirent.h>
#endif /** WIN32 */
#include <time.h>
#include "projectM.h"
#include "wipemalloc.h"
#include "common.h"
#include "compare.h"
#include "fatal.h"
#include "CustomWave.h"
#include "CustomShape.h"
#include "Expr.h"
#include "Eval.h"
#include "Func.h"
#include "InitCond.h"
#include "Param.h"
#include "Parser.h"
#include "PerFrameEqn.h"
#include "PerPixelEqn.h"
#include "Preset.h"
#include "SplayTree.h"
Preset *preset_hack;
Preset *Preset::active_preset = NULL;
Preset *Preset::idle_preset = NULL;
Preset *Preset::old_preset = NULL;
FILE * write_stream = NULL;
/** Initialise the idle preset */
Preset *Preset::init_idle_preset() {
Preset *preset = NULL;
/* Initialize idle preset struct */
if ((preset = (Preset*)wipemalloc(sizeof(Preset))) == NULL)
return NULL;
strncpy(preset->name, "idlepreset", strlen("idlepreset"));
/* Initialize equation trees */
preset->init_cond_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_string, (void*(*)(void*))copy_string, (void(*)(void*))free_string);
preset->user_param_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_string,(void*(*)(void*)) copy_string, (void(*)(void*))free_string);
preset->per_frame_eqn_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_int,(void*(*)(void*)) copy_int, (void(*)(void*))free_int);
preset->per_pixel_eqn_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_int, (void*(*)(void*))copy_int, (void(*)(void*))free_int);
preset->per_frame_init_eqn_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_string,(void*(*)(void*)) copy_string, (void(*)(void*))free_string);
preset->custom_wave_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_int, (void*(*)(void*))copy_int, (void(*)(void*))free_int);
preset->custom_shape_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_int,(void*(*)(void*)) copy_int, (void(*)(void*))free_int);
/* Set file path to dummy name */
strncpy(preset->file_path, "IDLE PRESET", MAX_PATH_SIZE-1);
/* Set initial index values */
preset->per_pixel_eqn_string_index = 0;
preset->per_frame_eqn_string_index = 0;
preset->per_frame_init_eqn_string_index = 0;
memset(preset->per_pixel_flag, 0, sizeof(int)*NUM_OPS);
/* Clear string buffers */
memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
memset(preset->per_frame_init_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
idle_preset = preset;
return preset;
}
int Preset::destroy_idle_preset() {
idle_preset->destroy();
idle_preset = NULL;
return PROJECTM_SUCCESS;
}
int Preset::destroy() {
return close_preset();
}
void Preset::evalCustomShapeInitConditions() {
custom_shape_tree->splay_traverse( eval_custom_shape_init_conds_helper );
}
void Preset::evalCustomWaveInitConditions() {
custom_wave_tree->splay_traverse( eval_custom_wave_init_conds_helper );
}
void Preset::evalInitConditions() {
per_frame_init_eqn_tree->splay_traverse((void (*)(void*))eval_init_cond_helper);
}
void Preset::evalPerFrameEquations() {
init_cond_tree->splay_traverse((void (*)(void*))eval_init_cond_helper);
per_frame_eqn_tree->splay_traverse((void (*)(void*))eval_per_frame_eqn_helper);
}
/* Private function to close a preset file */
int Preset::close_preset() {
#if defined(PRESET_DEBUG) && defined(DEBUG)
DWRITE( "close_preset(): in\n" );
#endif
init_cond_tree->splay_traverse((void (*)(void*))free_init_cond_helper);
delete init_cond_tree;
per_frame_init_eqn_tree->splay_traverse((void (*)(void*))free_init_cond_helper);
delete per_frame_init_eqn_tree;
per_pixel_eqn_tree->splay_traverse((void (*)(void*))free_per_pixel_eqn_helper);
delete per_pixel_eqn_tree;
per_frame_eqn_tree->splay_traverse((void (*)(void*))free_per_frame_eqn_helper);
delete per_frame_eqn_tree;
user_param_tree->splay_traverse((void (*)(void*))free_param_helper);
delete user_param_tree;
custom_wave_tree->splay_traverse((void (*)(void*))free_custom_wave_helper);
delete custom_wave_tree;
custom_shape_tree->splay_traverse((void (*)(void*))free_custom_shape_helper);
delete custom_shape_tree;
#if defined(PRESET_DEBUG) && defined(DEBUG)
DWRITE( "close_preset(): out\n" );
#endif
return PROJECTM_SUCCESS;
}
void Preset::reloadPerPixel(char *s) {
int slen;
if (s == NULL)
return;
/* Clear previous per pixel equations */
per_pixel_eqn_tree->splay_traverse((void (*)(void*))free_per_pixel_eqn_helper);
delete per_pixel_eqn_tree;
per_pixel_eqn_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_int, (void* (*)(void*))copy_int, (void (*)(void*))free_int);
/* Convert string to a stream */
#if !defined(MACOS) && !defined(WIN32)
{
FILE* fs = fmemopen (s, strlen(s), "r");
char c;
while ((c = fgetc(fs)) != EOF) {
ungetc(c, fs);
//FIXME Parser::parse_per_pixel_eqn(fs, preset, 0);
}
fclose(fs);
}
#else
printf( "reloadPerPixel()\n" );
#endif
/* Clear string space */
memset(per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
/* Compute length of string */
slen = strlen(s);
/* Copy new string into buffer */
strncpy(per_pixel_eqn_string_buffer, s, slen);
/* Yet again no bounds checking */
per_pixel_eqn_string_index = slen;
/* Finished */
return;
}
/* Obviously unwritten */
void Preset::reloadPerFrameInit(char *s) {
}
void Preset::reloadPerFrame(char * s) {
int slen;
int eqn_count = 1;
if (s == NULL)
return;
/* Clear previous per frame equations */
per_frame_eqn_tree->splay_traverse((void (*)(void*))free_per_frame_eqn_helper );
delete per_frame_eqn_tree;
per_frame_eqn_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_int,(void* (*)(void*)) copy_int, (void (*)(void*))free_int);
/* Convert string to a stream */
//FIXME
#if !defined(MACOS) && !defined(WIN32) && !defined(LINUX)
{
FILE* fs = fmemopen (s, strlen(s), "r");
char c;
while ((c = fgetc(fs)) != EOF) {
per_frame_eqn_t * per_frame;
ungetc(c, fs);
if ((per_frame = Parser::parse_per_frame_eqn(fs, eqn_count, preset)) != NULL) {
splay_insert(per_frame, &eqn_count, preset->per_frame_eqn_tree);
eqn_count++;
}
}
fclose(fs);
}
#else
printf( "reloadPerFrame()\n" );
#endif
/* Clear string space */
memset(per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
/* Compute length of string */
slen = strlen(s);
/* Copy new string into buffer */
strncpy(per_frame_eqn_string_buffer, s, slen);
/* Yet again no bounds checking */
per_frame_eqn_string_index = slen;
/* Finished */
printf("reloadPerFrame: %d eqns parsed succesfully\n", eqn_count-1);
return;
}
Preset * Preset::load_preset(const char * pathname) {
Preset * preset;
printf( "loading preset from '%s'\n", pathname );
/* Initialize preset struct */
if ((preset = (Preset*)wipemalloc(sizeof(Preset))) == NULL)
return NULL;
/* Initialize equation trees */
preset->init_cond_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_string, (void* (*)(void*))copy_string, (void (*)(void*))free_string);
preset->user_param_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_string,(void* (*)(void*)) copy_string, (void (*)(void*))free_string);
preset->per_frame_eqn_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_int,(void* (*)(void*)) copy_int, (void (*)(void*)) free_int);
preset->per_pixel_eqn_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_int,(void* (*)(void*)) copy_int, (void (*)(void*)) free_int);
preset->per_frame_init_eqn_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_string,(void* (*)(void*)) copy_string, (void (*)(void*)) free_string);
preset->custom_wave_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_int, (void* (*)(void*))copy_int, (void (*)(void*)) free_int);
preset->custom_shape_tree = SplayTree::create_splaytree((int (*)(void*,void*))compare_int, (void* (*)(void*))copy_int, (void (*)(void*)) free_int);
memset(preset->per_pixel_flag, 0, sizeof(int)*NUM_OPS);
/* Copy file path */
if ( pathname == NULL ) {
preset->close_preset();
return NULL;
}
strncpy(preset->file_path, pathname, MAX_PATH_SIZE-1);
/* Set initial index values */
preset->per_pixel_eqn_string_index = 0;
preset->per_frame_eqn_string_index = 0;
preset->per_frame_init_eqn_string_index = 0;
/* Clear string buffers */
memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
memset(preset->per_frame_init_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
if (projectM::currentEngine->load_preset_file(pathname, preset) < 0) {
#ifdef PRESET_DEBUG
if (PRESET_DEBUG) printf("load_preset: failed to load file \"%s\"\n", pathname);
#endif
preset->close_preset();
return NULL;
}
/* It's kind of ugly to reset these values here. Should definitely be placed in the parser somewhere */
preset->per_frame_eqn_count = 0;
preset->per_frame_init_eqn_count = 0;
/* Finished, return new preset */
return preset;
}
void Preset::savePreset(char * filename) {
#ifdef PANTS
FILE * fs;
if (filename == NULL)
return;
/* Open the file corresponding to pathname */
if ((fs = fopen(filename, "w+")) == 0) {
#ifdef PRESET_DEBUG
if (PRESET_DEBUG) printf("savePreset: failed to create filename \"%s\"!\n", filename);
#endif
return;
}
write_stream = fs;
if (write_preset_name(fs) < 0) {
write_stream = NULL;
fclose(fs);
return;
}
if (write_init_conditions(fs) < 0) {
write_stream = NULL;
fclose(fs);
return;
}
if (write_per_frame_init_equations(fs) < 0) {
write_stream = NULL;
fclose(fs);
return;
}
if (write_per_frame_equations(fs) < 0) {
write_stream = NULL;
fclose(fs);
return;
}
if (write_per_pixel_equations(fs) < 0) {
write_stream = NULL;
fclose(fs);
return;
}
write_stream = NULL;
fclose(fs);
#endif
}
int Preset::write_preset_name(FILE * fs) {
char s[256];
int len;
memset(s, 0, 256);
if (fs == NULL)
return PROJECTM_FAILURE;
/* Format the preset name in a string */
sprintf(s, "[%s]\n", name);
len = strlen(s);
/* Write preset name to file stream */
if (fwrite(s, 1, len, fs) != len)
return PROJECTM_FAILURE;
return PROJECTM_SUCCESS;
}
#ifdef NEEDS_MOVED
int Preset::write_init_conditions(FILE * fs) {
if (fs == NULL)
return PROJECTM_FAILURE;
init_cond_tree->splay_traverse( (void (*)(void*))write_init);
return PROJECTM_SUCCESS;
}
void Preset::write_init( InitCond * init_cond ) {
char s[512];
int len;
if (write_stream == NULL)
return;
memset(s, 0, 512);
if (init_cond->param->type == P_TYPE_BOOL)
sprintf(s, "%s=%d\n", init_cond->param->name, init_cond->init_val.bool_val);
else if (init_cond->param->type == P_TYPE_INT)
sprintf(s, "%s=%d\n", init_cond->param->name, init_cond->init_val.int_val);
else if (init_cond->param->type == P_TYPE_DOUBLE)
sprintf(s, "%s=%f\n", init_cond->param->name, init_cond->init_val.float_val);
else { printf("write_init: unknown parameter type!\n"); return; }
len = strlen(s);
if ((fwrite(s, 1, len, write_stream)) != len)
printf("write_init: failed writing to file stream! Out of disk space?\n");
}
int Preset::write_per_frame_init_equations(FILE * fs) {
int len;
if (fs == NULL)
return PROJECTM_FAILURE;
len = strlen(per_frame_init_eqn_string_buffer);
if (fwrite(per_frame_init_eqn_string_buffer, 1, len, fs) != len)
return PROJECTM_FAILURE;
return PROJECTM_SUCCESS;
}
int Preset::write_per_frame_equations(FILE * fs) {
int len;
if (fs == NULL)
return PROJECTM_FAILURE;
len = strlen(per_frame_eqn_string_buffer);
if (fwrite(per_frame_eqn_string_buffer, 1, len, fs) != len)
return PROJECTM_FAILURE;
return PROJECTM_SUCCESS;
}
int Preset::write_per_pixel_equations(FILE * fs) {
int len;
if (fs == NULL)
return PROJECTM_FAILURE;
len = strlen(per_pixel_eqn_string_buffer);
if (fwrite(per_pixel_eqn_string_buffer, 1, len, fs) != len)
return PROJECTM_FAILURE;
return PROJECTM_SUCCESS;
}
#endif /** NEEDS_MOVED */
void Preset::load_custom_wave_init_conditions() {
custom_wave_tree->splay_traverse((void (*)(void*))load_custom_wave_init_helper);
}
void Preset::load_custom_shape_init_conditions() {
custom_shape_tree->splay_traverse((void (*)(void*))load_custom_shape_init_helper);
}
/** Returns the next custom waveform in the wave database */
CustomWave *Preset::nextCustomWave() {
CustomWave *interface_wave = NULL;
if ( (interface_wave = (CustomWave *)custom_wave_tree->splay_find(&interface_id) ) == NULL ) {
interface_id = 0;
return interface_wave;
}
interface_id++;
/** Evaluate all per frame equations associated with this wave */
interface_wave->init_cond_tree->splay_traverse((void (*)(void*))eval_init_cond_helper);
interface_wave->per_frame_eqn_tree->splay_traverse((void (*)(void*))eval_per_frame_eqn_helper);
return interface_wave;
}
/** Returns the next custom shape in the shape database */
CustomShape *Preset::nextCustomShape() {
CustomShape *interface_shape = NULL;
if ( (interface_shape = (CustomShape *)custom_shape_tree->splay_find(&cwave_interface_id) ) == NULL ) {
cwave_interface_id = 0;
return interface_shape;
}
cwave_interface_id++;
/** Evaluate all per frame equations associated with this wave */
interface_shape->init_cond_tree->splay_traverse((void (*)(void*))eval_init_cond_helper);
interface_shape->per_frame_eqn_tree->splay_traverse((void (*)(void*))eval_per_frame_eqn_helper);
return interface_shape;
}
/** Evaluates all per-pixel equations */
void Preset::evalPerPixelEqns() {
/* Evaluate all per pixel equations using splay traversal */
per_pixel_eqn_tree->splay_traverse((void (*)(void*))eval_per_pixel_eqn_helper);
/* Set mesh i / j values to -1 so engine vars are used by default again */
projectM::currentEngine->mesh_i = -1;
projectM::currentEngine->mesh_j = -1;
}
/** Is the opcode a per-pixel equation? */
int Preset::isPerPixelEqn( int op ) {
return per_pixel_flag[op];
}
/** Reset all per-pixel equation flags */
int Preset::resetPerPixelEqnFlags() {
int i;
for (i = 0; i < NUM_OPS;i++) {
per_pixel_flag[i] = FALSE;
}
return PROJECTM_SUCCESS;
}
/* Adds a per pixel equation according to its string name. This
will be used only by the parser */
int Preset::add_per_pixel_eqn(char * name, GenExpr * gen_expr) {
PerPixelEqn * per_pixel_eqn = NULL;
int index;
Param * param = NULL;
/* Argument checks */
if (gen_expr == NULL)
return PROJECTM_FAILURE;
if (name == NULL)
return PROJECTM_FAILURE;
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: per pixel equation (name = \"%s\")\n", name);
if (!strncmp(name, "dx", strlen("dx")))
per_pixel_flag[DX_OP] = TRUE;
else if (!strncmp(name, "dy", strlen("dy")))
per_pixel_flag[DY_OP] = TRUE;
else if (!strncmp(name, "cx", strlen("cx")))
per_pixel_flag[CX_OP] = TRUE;
else if (!strncmp(name, "cy", strlen("cy")))
per_pixel_flag[CX_OP] = TRUE;
else if (!strncmp(name, "zoom", strlen("zoom")))
per_pixel_flag[ZOOM_OP] = TRUE;
else if (!strncmp(name, "zoomexp", strlen("zoomexp")))
per_pixel_flag[ZOOMEXP_OP] = TRUE;
else if (!strncmp(name, "rot", strlen("rot")))
per_pixel_flag[ROT_OP] = TRUE;
else if (!strncmp(name, "sx", strlen("sx")))
per_pixel_flag[SX_OP] = TRUE;
else if (!strncmp(name, "sy", strlen("sy")))
per_pixel_flag[SY_OP] = TRUE;
/* Search for the parameter so we know what matrix the per pixel equation is referencing */
param = Param::find_param(name, this, TRUE);
if ( !param ) {
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to allocate a new parameter!\n");
return PROJECTM_FAILURE;
}
/**
if ( !param->matrix ) {
if (PER_PIXEL_EQN_DEBUG) printf( "add_per_pixel_eqn: failed to locate param matrix\n" );
return PROJECTM_FAILURE;
}
*/
/* Find most largest index in the splaytree */
if ((per_pixel_eqn = (PerPixelEqn *)per_pixel_eqn_tree->splay_find_max()) == NULL)
index = 0;
else
index = per_pixel_eqn_tree->splay_size();
/* Create the per pixel equation given the index, parameter, and general expression */
if ((per_pixel_eqn = PerPixelEqn::new_per_pixel_eqn(index, param, gen_expr)) == NULL) {
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to create new per pixel equation!\n");
return PROJECTM_FAILURE;
}
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: new equation (index = %d,matrix=%X) (param = \"%s\")\n",
per_pixel_eqn->index, per_pixel_eqn->param->matrix, per_pixel_eqn->param->name);
/* Insert the per pixel equation into the preset per pixel database */
if (per_pixel_eqn_tree->splay_insert(per_pixel_eqn, &per_pixel_eqn->index) < 0) {
per_pixel_eqn->free_per_pixel_eqn();
printf("failed to add per pixel eqn!\n");
return PROJECTM_FAILURE;
}
/* Done */
return PROJECTM_SUCCESS;
}
/* Finds / Creates (if necessary) initial condition associated with passed parameter */
InitCond *Preset::get_init_cond( Param *param ) {
InitCond * init_cond;
CValue init_val;
if ( param == NULL ) {
return NULL;
}
if ((init_cond = (InitCond*)(init_cond_tree->splay_find(param->name))) == NULL) {
if (param->type == P_TYPE_BOOL)
init_val.bool_val = 0;
else if (param->type == P_TYPE_INT)
init_val.int_val = *(int*)param->engine_val;
else if (param->type == P_TYPE_DOUBLE)
init_val.float_val = *(float*)param->engine_val;
/* Create new initial condition */
if ((init_cond = new InitCond(param, init_val)) == NULL)
return NULL;
/* Insert the initial condition into this presets tree */
if (init_cond_tree->splay_insert(init_cond, init_cond->param->name) < 0) {
delete init_cond;
return NULL;
}
}
return init_cond;
}