From 9903e524f13d3d89bde6fcb30fe0048fc2ec2db9 Mon Sep 17 00:00:00 2001 From: w1z7ard Date: Wed, 6 Aug 2008 04:57:46 +0000 Subject: [PATCH] first step of rehashing Preset definition git-svn-id: https://projectm.svn.sourceforge.net/svnroot/projectm/personal/carm/represet@1127 6778bc44-b910-0410-a7a0-be141de4315d --- src/libprojectM/MilkdropPreset.cpp | 530 +++++++++++++++++++++++++++++ src/libprojectM/MilkdropPreset.hpp | 246 +++++++++++++ src/libprojectM/Preset.cpp | 529 +--------------------------- src/libprojectM/Preset.hpp | 254 ++------------ 4 files changed, 810 insertions(+), 749 deletions(-) create mode 100755 src/libprojectM/MilkdropPreset.cpp create mode 100644 src/libprojectM/MilkdropPreset.hpp diff --git a/src/libprojectM/MilkdropPreset.cpp b/src/libprojectM/MilkdropPreset.cpp new file mode 100755 index 000000000..b6a2f06dd --- /dev/null +++ b/src/libprojectM/MilkdropPreset.cpp @@ -0,0 +1,530 @@ +/** + * 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 +#include +#include +#ifdef WIN32 +#include "win32-dirent.h" +#else +#include +#endif /** WIN32 */ +#include + +#include "MilkdropPreset.hpp" +#include "Parser.hpp" +#include "ParamUtils.hpp" +#include "InitCondUtils.hpp" +#include "fatal.h" +#include +#include + + +MilkdropPreset::MilkdropPreset(std::istream & in, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs): + builtinParams(presetInputs, presetOutputs), + m_presetName(presetName), + m_presetOutputs(presetOutputs), + m_presetInputs(presetInputs) +{ + + m_presetOutputs.customWaves.clear(); + m_presetOutputs.customShapes.clear(); + + initialize(in); + +} + + +MilkdropPreset::MilkdropPreset(const std::string & absoluteFilePath, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs): + builtinParams(presetInputs, presetOutputs), + m_absoluteFilePath(absoluteFilePath), + m_presetName(presetName), + m_presetOutputs(presetOutputs), + m_presetInputs(presetInputs) +{ + + m_presetOutputs.customWaves.clear(); + m_presetOutputs.customShapes.clear(); + + initialize(absoluteFilePath); + +} + +Preset::~MilkdropPreset() +{ + + Algorithms::traverse >(init_cond_tree); + + Algorithms::traverse >(per_frame_init_eqn_tree); + + Algorithms::traverse >(per_pixel_eqn_tree); + + Algorithms::traverseVector >(per_frame_eqn_tree); + + Algorithms::traverse >(user_param_tree); + + for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) + { + delete(*pos); + } + + for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) + { + delete(*pos); + } + +} + +/* Adds a per pixel equation according to its string name. This + will be used only by the parser */ + +int MilkdropPreset::add_per_pixel_eqn(char * name, GenExpr * gen_expr) +{ + + PerPixelEqn * per_pixel_eqn = NULL; + int index; + Param * param = NULL; + + assert(gen_expr); + assert(name); + + if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: per pixel equation (name = \"%s\")\n", name); + + + /* Search for the parameter so we know what matrix the per pixel equation is referencing */ + + param = ParamUtils::find(name, &this->builtinParams, &this->user_param_tree); + if ( !param ) + { + if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to allocate a new parameter!\n"); + return PROJECTM_FAILURE; + } + + index = per_pixel_eqn_tree.size(); + + /* Create the per pixel equation given the index, parameter, and general expression */ + if ((per_pixel_eqn = new PerPixelEqn(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; + } + + + + /* Insert the per pixel equation into the preset per pixel database */ + std::pair::iterator, bool> inserteeOption = per_pixel_eqn_tree.insert + (std::make_pair(per_pixel_eqn->index, per_pixel_eqn)); + + if (!inserteeOption.second) + { + printf("failed to add per pixel eqn!\n"); + delete(per_pixel_eqn); + return PROJECTM_FAILURE; + } + + /* Done */ + return PROJECTM_SUCCESS; +} + +void MilkdropPreset::evalCustomShapeInitConditions() +{ + + for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) { + assert(*pos); + (*pos)->evalInitConds(); + } +} + + +void MilkdropPreset::evalCustomWaveInitConditions() +{ + + for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) { + assert(*pos); + (*pos)->evalInitConds(); +} +} + + +void MilkdropPreset::evalCustomWavePerFrameEquations() +{ + + for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) + { + + std::map & init_cond_tree = (*pos)->init_cond_tree; + for (std::map::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos) + { + assert(_pos->second); + _pos->second->evaluate(); + } + + std::vector & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree; + for (std::vector::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos) + { + (*_pos)->evaluate(); + } + } + +} + +void MilkdropPreset::evalCustomShapePerFrameEquations() +{ + + for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) + { + + std::map & init_cond_tree = (*pos)->init_cond_tree; + for (std::map::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos) + { + assert(_pos->second); + _pos->second->evaluate(); + } + + std::vector & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree; + for (std::vector::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos) + { + (*_pos)->evaluate(); + } + } + +} + +void MilkdropPreset::evalPerFrameInitEquations() +{ + + for (std::map::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos) + { + assert(pos->second); + pos->second->evaluate(); + } + +} + +void MilkdropPreset::evalPerFrameEquations() +{ + + for (std::map::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos) + { + assert(pos->second); + pos->second->evaluate(); + } + + for (std::vector::iterator pos = per_frame_eqn_tree.begin(); pos != per_frame_eqn_tree.end(); ++pos) + { + (*pos)->evaluate(); + } + +} + +void MilkdropPreset::preloadInitialize() { + + /// @note commented this out because it should be unnecessary + // Clear equation trees + //init_cond_tree.clear(); + //user_param_tree.clear(); + //per_frame_eqn_tree.clear(); + //per_pixel_eqn_tree.clear(); + //per_frame_init_eqn_tree.clear(); + + +} + +void MilkdropPreset::postloadInitialize() { + + /* It's kind of ugly to reset these values here. Should definitely be placed in the parser somewhere */ + this->per_frame_eqn_count = 0; + this->per_frame_init_eqn_count = 0; + + this->loadBuiltinParamsUnspecInitConds(); + this->loadCustomWaveUnspecInitConds(); + this->loadCustomShapeUnspecInitConds(); + + +/// @bug are you handling all the q variables conditions? in particular, the un-init case? +//m_presetOutputs.q1 = 0; +//m_presetOutputs.q2 = 0; +//m_presetOutputs.q3 = 0; +//m_presetOutputs.q4 = 0; +//m_presetOutputs.q5 = 0; +//m_presetOutputs.q6 = 0; +//m_presetOutputs.q7 = 0; +//m_presetOutputs.q8 = 0; + +} + +void MilkdropPreset::initialize(const std::string & pathname) +{ + int retval; + + preloadInitialize(); + +if (PRESET_DEBUG) + std::cerr << "[Preset] loading file \"" << pathname << "\"..." << std::endl; + + if ((retval = loadPresetFile(pathname)) < 0) + { +if (PRESET_DEBUG) + std::cerr << "[Preset] failed to load file \"" << + pathname << "\"!" << std::endl; + + /// @bug how should we handle this problem? a well define exception? + throw retval; + } + + postloadInitialize(); +} + +void MilkdropPreset::initialize(std::istream & in) +{ + int retval; + + preloadInitialize(); + + if ((retval = readIn(in)) < 0) + { + + if (PRESET_DEBUG) + std::cerr << "[Preset] failed to load from stream " << std::endl; + + /// @bug how should we handle this problem? a well define exception? + throw retval; + } + + postloadInitialize(); +} + +void MilkdropPreset::loadBuiltinParamsUnspecInitConds() { + + InitCondUtils::LoadUnspecInitCond loadUnspecInitCond(this->init_cond_tree, this->per_frame_init_eqn_tree); + + this->builtinParams.traverse(loadUnspecInitCond); + Algorithms::traverse(user_param_tree, loadUnspecInitCond); + +} + +void MilkdropPreset::loadCustomWaveUnspecInitConds() +{ + + + for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) + { + assert(*pos); + (*pos)->loadUnspecInitConds(); + } + +} + +void MilkdropPreset::loadCustomShapeUnspecInitConds() +{ + + for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) + { + assert(*pos); + (*pos)->loadUnspecInitConds(); + } +} + + +void MilkdropPreset::evaluateFrame() +{ + + // Evaluate all equation objects according to milkdrop flow diagram + + evalPerFrameInitEquations(); + evalPerFrameEquations(); + + // Important step to ensure custom shapes and waves don't stamp on the q variable values + // calculated by the per frame (init) and per pixel equations. + transfer_q_variables(customWaves); + transfer_q_variables(customShapes); + + initialize_PerPixelMeshes(); + + evalPerPixelEqns(); + + evalCustomWaveInitConditions(); + evalCustomWavePerFrameEquations(); + + evalCustomShapeInitConditions(); + evalCustomShapePerFrameEquations(); + + // Setup pointers of the custom waves and shapes to the preset outputs instance + /// @slow an extra O(N) per frame, could do this during eval + m_presetOutputs.customWaves = PresetOutputs::cwave_container(customWaves); + m_presetOutputs.customShapes = PresetOutputs::cshape_container(customShapes); + +} + +void MilkdropPreset::initialize_PerPixelMeshes() +{ + + int x,y; + for (x=0;x::iterator pos = per_pixel_eqn_tree.begin(); + pos != per_pixel_eqn_tree.end(); ++pos) + pos->second->evaluate(mesh_x, mesh_y); + +} + +int MilkdropPreset::readIn(std::istream & fs) { + + line_mode_t line_mode; + presetOutputs().compositeShader.programSource.clear(); + presetOutputs().warpShader.programSource.clear(); + + /* Parse any comments */ + if (Parser::parse_top_comment(fs) < 0) + { + if (PRESET_DEBUG) + std::cerr << "[Preset::readIn] no left bracket found..." << std::endl; + return PROJECTM_FAILURE; + } + + /* Parse the preset name and a left bracket */ + char tmp_name[MAX_TOKEN_SIZE]; + + if (Parser::parse_preset_name(fs, tmp_name) < 0) + { + std::cerr << "[Preset::readIn] loading of preset name failed" << std::endl; + return PROJECTM_ERROR; + } + + /// @note We ignore the preset name because [preset00] is just not so useful + + // Loop through each line in file, trying to succesfully parse the file. + // If a line does not parse correctly, keep trucking along to next line. + int retval; + while ((retval = Parser::parse_line(fs, this)) != EOF) + { + if (retval == PROJECTM_PARSE_ERROR) + { + line_mode = UNSET_LINE_MODE; + // std::cerr << "[Preset::readIn()] parse error in file \"" << this->absoluteFilePath() << "\"" << std::endl; + } + } + +// std::cerr << "loadPresetFile: finished line parsing successfully" << std::endl; + + /* Now the preset has been loaded. + Evaluation calls can be made at appropiate + times in the frame loop */ + +return PROJECTM_SUCCESS; +} + +/* loadPresetFile: private function that loads a specific preset denoted + by the given pathname */ +int MilkdropPreset::loadPresetFile(const std::string & pathname) +{ + + + /* Open the file corresponding to pathname */ + std::ifstream fs(pathname.c_str()); + if (!fs || fs.eof()) { + if (PRESET_DEBUG) + std::cerr << "loadPresetFile: loading of file \"" << pathname << "\" failed!\n"; + return PROJECTM_ERROR; + } + + return readIn(fs); + +} + diff --git a/src/libprojectM/MilkdropPreset.hpp b/src/libprojectM/MilkdropPreset.hpp new file mode 100644 index 000000000..efbb15445 --- /dev/null +++ b/src/libprojectM/MilkdropPreset.hpp @@ -0,0 +1,246 @@ + +/** + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2007 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 + * + */ +/** + * $Id$ + * + * MilkdropPreset + * + * $Log$ + */ + +#ifndef _MilkdropPreset_HPP +#define _MilkdropPreset_HPP + +#include "Common.hpp" +#include +#include +#include + +#define MilkdropPreset_DEBUG 0 /* 0 for no debugging, 1 for normal, 2 for insane */ + +#include "CustomShape.hpp" +#include "CustomWave.hpp" +#include "Expr.hpp" +#include "PerPixelEqn.hpp" +#include "PerFrameEqn.hpp" +#include "BuiltinParams.hpp" +#include "PresetFrameIO.hpp" +#include "InitCond.hpp" + +class CustomWave; +class CustomShape; +class InitCond; + + +class MilkdropPreset : public Preset +{ +protected: + +public: + + + /// Load a MilkdropPreset by filename with input and output buffers specified. + /// \param absoluteFilePath the absolute file path of a MilkdropPreset to load from the file system + /// \param MilkdropPresetName a descriptive name for the MilkdropPreset. Usually just the file name + /// \param MilkdropPresetInputs a reference to read only projectM engine variables + /// \param MilkdropPresetOutputs initialized and filled with data parsed from a MilkdropPreset + MilkdropPreset(const std::string & absoluteFilePath, const std::string & MilkdropPresetName, MilkdropPresetInputs & MilkdropPresetInputs, MilkdropPresetOutputs & MilkdropPresetOutputs); + + /// Load a MilkdropPreset from an input stream with input and output buffers specified. + /// \param in an already initialized input stream to read the MilkdropPreset file from + /// \param MilkdropPresetName a descriptive name for the MilkdropPreset. Usually just the file name + /// \param MilkdropPresetInputs a reference to read only projectM engine variables + /// \param MilkdropPresetOutputs initialized and filled with data parsed from a MilkdropPreset + MilkdropPreset(std::istream & in, const std::string & MilkdropPresetName, MilkdropPresetInputs & MilkdropPresetInputs, MilkdropPresetOutputs & MilkdropPresetOutputs); + + ~MilkdropPreset(); + + /// Evaluates the MilkdropPreset for a frame given the current values of MilkdropPreset inputs / outputs + /// All calculated values are stored in the associated MilkdropPreset outputs instance + void evaluateFrame(); + + /// All "builtin" parameters for this MilkdropPreset. Anything *but* user defined parameters and + /// custom waves / shapes objects go here. + /// @bug encapsulate + BuiltinParams builtinParams; + + + /// Used by parser to find/create custom waves and shapes. May be refactored + template + static CustomObject * find_custom_object(int id, std::vector & customObjects); + + + int per_pixel_eqn_string_index; + int per_frame_eqn_string_index; + int per_frame_init_eqn_string_index; + + int per_frame_eqn_count, + per_frame_init_eqn_count; + + + /// Used by parser + /// @bug refactor + int add_per_pixel_eqn( char *name, GenExpr *gen_expr ); + + /// Accessor method to retrieve the absolute file path of the loaded MilkdropPreset + /// \returns a file path string + std::string absoluteFilePath() const + { + return m_absoluteFilePath; + } + + + /// Accessor method for the MilkdropPreset outputs instance associated with this MilkdropPreset + /// \returns A MilkdropPreset output instance with values computed from most recent evaluateFrame() + MilkdropPresetOutputs & MilkdropPresetOutputs() const + { + + return m_MilkdropPresetOutputs; + } + + MilkdropPresetInputs & MilkdropPresetInputs() const + { + + return m_PresetInputs; + } + /// Sets the descriptive name for this MilkdropPreset (typically the file name) + /// \param theValue the new MilkdropPreset name to assign to the MilkdropPreset + void setPresetName ( const std::string& theValue ) + { + m_PresetName = theValue; + } + + /// Gets the descriptive name for this MilkdropPreset (typically the file name) + /// \returns the name of the MilkdropPreset + std::string MilkPresetName() const + { + return m_PresetName; + } + + /// @bug encapsulate + + PresetOutputs::cwave_container customWaves; + PresetOutputs::cshape_container customShapes; + + /// @bug encapsulate + /* Data structures that contain equation and initial condition information */ + std::vector per_frame_eqn_tree; /* per frame equations */ + std::map per_pixel_eqn_tree; /* per pixel equation tree */ + std::map per_frame_init_eqn_tree; /* per frame initial equations */ + std::map init_cond_tree; /* initial conditions */ + std::map user_param_tree; /* user parameter splay tree */ + +private: + + // The absolute file path of the MilkdropPreset + std::string m_absoluteFilePath; + + // The absolute path of the MilkdropPreset + std::string m_absolutePath; + + // The name for the MilkdropPreset. Usually the file name, but in theory anything goes + std::string m_MilkdropPresetName; + + void initialize(const std::string & pathname); + void initialize(std::istream & in); + + int loadPresetFile(const std::string & pathname); + + void loadBuiltinParamsUnspecInitConds(); + void loadCustomWaveUnspecInitConds(); + void loadCustomShapeUnspecInitConds(); + + void evalCustomWavePerFrameEquations(); + void evalCustomShapePerFrameEquations(); + void evalPerFrameInitEquations(); + void evalCustomWaveInitConditions(); + void evalCustomShapeInitConditions(); + void evalPerPixelEqns(); + void evalPerFrameEquations(); + void initialize_PerPixelMeshes(); + int readIn(std::istream & fs); + + void preloadInitialize(); + void postloadInitialize(); + + PresetOutputs & m_PresetOutputs; + PresetInputs & m_PresetInputs; // added for gx, gy reference. + +template +void transfer_q_variables(std::vector & customObjects); +}; + + +template +void MilkdropPreset::transfer_q_variables(std::vector & customObjects) +{ + CustomObject * custom_object; + + for (typename std::vector::iterator pos = customObjects.begin(); pos != customObjects.end();++pos) { + + custom_object = *pos; + custom_object->q1 = m_MilkdropPresetOutputs.q[0]; + custom_object->q2 = m_MilkdropPresetOutputs.q[1]; + custom_object->q3 = m_MilkdropPresetOutputs.q[2]; + custom_object->q4 = m_MilkdropPresetOutputs.q[3]; + custom_object->q5 = m_MilkdropPresetOutputs.q[4]; + custom_object->q6 = m_MilkdropPresetOutputs.q[5]; + custom_object->q7 = m_MilkdropPresetOutputs.q[6]; + custom_object->q8 = m_MilkdropPresetOutputs.q[7]; + } + + +} + +template +CustomObject * MilkdropPreset::find_custom_object(int id, std::vector & customObjects) +{ + + CustomObject * custom_object = NULL; + + + for (typename std::vector::iterator pos = customObjects.begin(); pos != customObjects.end();++pos) { + if ((*pos)->id == id) { + custom_object = *pos; + break; + } + } + + if (custom_object == NULL) + { + + if ((custom_object = new CustomObject(id)) == NULL) + { + return NULL; + } + + customObjects.push_back(custom_object); + + } + + assert(custom_object); + return custom_object; +} + + + +#endif /** !_MilkdropPreset_HPP */ diff --git a/src/libprojectM/Preset.cpp b/src/libprojectM/Preset.cpp index 8dc76b769..d942f72a7 100755 --- a/src/libprojectM/Preset.cpp +++ b/src/libprojectM/Preset.cpp @@ -1,530 +1,25 @@ -/** - * 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 +/* + * Preset.cpp * + * Created on: Aug 5, 2008 + * Author: carm */ -#include -#include -#include -#ifdef WIN32 -#include "win32-dirent.h" -#else -#include -#endif /** WIN32 */ -#include - #include "Preset.hpp" -#include "Parser.hpp" -#include "ParamUtils.hpp" -#include "InitCondUtils.hpp" -#include "fatal.h" -#include -#include +Preset::Preset() {} -Preset::Preset(std::istream & in, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs): - builtinParams(presetInputs, presetOutputs), - m_presetName(presetName), - m_presetOutputs(presetOutputs), - m_presetInputs(presetInputs) -{ +Preset::~Preset() {} - m_presetOutputs.customWaves.clear(); - m_presetOutputs.customShapes.clear(); +Preset::Preset(const std::string & presetName, const std::string & presetAuthor): + _name(presetName), _author(presetAuthor) {} - initialize(in); +void Preset::setName(const std::string & value) { _name = value; } -} +const std::string & Preset::name() const { return _name; } +void setAuthor(const std::string & value) { _author = value; } -Preset::Preset(const std::string & absoluteFilePath, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs): - builtinParams(presetInputs, presetOutputs), - m_absoluteFilePath(absoluteFilePath), - m_presetName(presetName), - m_presetOutputs(presetOutputs), - m_presetInputs(presetInputs) -{ +const std::string & author() const { return _author; } - m_presetOutputs.customWaves.clear(); - m_presetOutputs.customShapes.clear(); - - initialize(absoluteFilePath); - -} - -Preset::~Preset() -{ - - Algorithms::traverse >(init_cond_tree); - - Algorithms::traverse >(per_frame_init_eqn_tree); - - Algorithms::traverse >(per_pixel_eqn_tree); - - Algorithms::traverseVector >(per_frame_eqn_tree); - - Algorithms::traverse >(user_param_tree); - - for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) - { - delete(*pos); - } - - for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) - { - delete(*pos); - } - -} - -/* 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; - - assert(gen_expr); - assert(name); - - if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: per pixel equation (name = \"%s\")\n", name); - - - /* Search for the parameter so we know what matrix the per pixel equation is referencing */ - - param = ParamUtils::find(name, &this->builtinParams, &this->user_param_tree); - if ( !param ) - { - if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to allocate a new parameter!\n"); - return PROJECTM_FAILURE; - } - - index = per_pixel_eqn_tree.size(); - - /* Create the per pixel equation given the index, parameter, and general expression */ - if ((per_pixel_eqn = new PerPixelEqn(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; - } - - - - /* Insert the per pixel equation into the preset per pixel database */ - std::pair::iterator, bool> inserteeOption = per_pixel_eqn_tree.insert - (std::make_pair(per_pixel_eqn->index, per_pixel_eqn)); - - if (!inserteeOption.second) - { - printf("failed to add per pixel eqn!\n"); - delete(per_pixel_eqn); - return PROJECTM_FAILURE; - } - - /* Done */ - return PROJECTM_SUCCESS; -} - -void Preset::evalCustomShapeInitConditions() -{ - - for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) { - assert(*pos); - (*pos)->evalInitConds(); - } -} - - -void Preset::evalCustomWaveInitConditions() -{ - - for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) { - assert(*pos); - (*pos)->evalInitConds(); -} -} - - -void Preset::evalCustomWavePerFrameEquations() -{ - - for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) - { - - std::map & init_cond_tree = (*pos)->init_cond_tree; - for (std::map::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos) - { - assert(_pos->second); - _pos->second->evaluate(); - } - - std::vector & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree; - for (std::vector::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos) - { - (*_pos)->evaluate(); - } - } - -} - -void Preset::evalCustomShapePerFrameEquations() -{ - - for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) - { - - std::map & init_cond_tree = (*pos)->init_cond_tree; - for (std::map::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos) - { - assert(_pos->second); - _pos->second->evaluate(); - } - - std::vector & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree; - for (std::vector::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos) - { - (*_pos)->evaluate(); - } - } - -} - -void Preset::evalPerFrameInitEquations() -{ - - for (std::map::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos) - { - assert(pos->second); - pos->second->evaluate(); - } - -} - -void Preset::evalPerFrameEquations() -{ - - for (std::map::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos) - { - assert(pos->second); - pos->second->evaluate(); - } - - for (std::vector::iterator pos = per_frame_eqn_tree.begin(); pos != per_frame_eqn_tree.end(); ++pos) - { - (*pos)->evaluate(); - } - -} - -void Preset::preloadInitialize() { - - /// @note commented this out because it should be unnecessary - // Clear equation trees - //init_cond_tree.clear(); - //user_param_tree.clear(); - //per_frame_eqn_tree.clear(); - //per_pixel_eqn_tree.clear(); - //per_frame_init_eqn_tree.clear(); - - -} - -void Preset::postloadInitialize() { - - /* It's kind of ugly to reset these values here. Should definitely be placed in the parser somewhere */ - this->per_frame_eqn_count = 0; - this->per_frame_init_eqn_count = 0; - - this->loadBuiltinParamsUnspecInitConds(); - this->loadCustomWaveUnspecInitConds(); - this->loadCustomShapeUnspecInitConds(); - - -/// @bug are you handling all the q variables conditions? in particular, the un-init case? -//m_presetOutputs.q1 = 0; -//m_presetOutputs.q2 = 0; -//m_presetOutputs.q3 = 0; -//m_presetOutputs.q4 = 0; -//m_presetOutputs.q5 = 0; -//m_presetOutputs.q6 = 0; -//m_presetOutputs.q7 = 0; -//m_presetOutputs.q8 = 0; - -} - -void Preset::initialize(const std::string & pathname) -{ - int retval; - - preloadInitialize(); - -if (PRESET_DEBUG) - std::cerr << "[Preset] loading file \"" << pathname << "\"..." << std::endl; - - if ((retval = loadPresetFile(pathname)) < 0) - { -if (PRESET_DEBUG) - std::cerr << "[Preset] failed to load file \"" << - pathname << "\"!" << std::endl; - - /// @bug how should we handle this problem? a well define exception? - throw retval; - } - - postloadInitialize(); -} - -void Preset::initialize(std::istream & in) -{ - int retval; - - preloadInitialize(); - - if ((retval = readIn(in)) < 0) - { - - if (PRESET_DEBUG) - std::cerr << "[Preset] failed to load from stream " << std::endl; - - /// @bug how should we handle this problem? a well define exception? - throw retval; - } - - postloadInitialize(); -} - -void Preset::loadBuiltinParamsUnspecInitConds() { - - InitCondUtils::LoadUnspecInitCond loadUnspecInitCond(this->init_cond_tree, this->per_frame_init_eqn_tree); - - this->builtinParams.traverse(loadUnspecInitCond); - Algorithms::traverse(user_param_tree, loadUnspecInitCond); - -} - -void Preset::loadCustomWaveUnspecInitConds() -{ - - - for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) - { - assert(*pos); - (*pos)->loadUnspecInitConds(); - } - -} - -void Preset::loadCustomShapeUnspecInitConds() -{ - - for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) - { - assert(*pos); - (*pos)->loadUnspecInitConds(); - } -} - - -void Preset::evaluateFrame() -{ - - // Evaluate all equation objects according to milkdrop flow diagram - - evalPerFrameInitEquations(); - evalPerFrameEquations(); - - // Important step to ensure custom shapes and waves don't stamp on the q variable values - // calculated by the per frame (init) and per pixel equations. - transfer_q_variables(customWaves); - transfer_q_variables(customShapes); - - initialize_PerPixelMeshes(); - - evalPerPixelEqns(); - - evalCustomWaveInitConditions(); - evalCustomWavePerFrameEquations(); - - evalCustomShapeInitConditions(); - evalCustomShapePerFrameEquations(); - - // Setup pointers of the custom waves and shapes to the preset outputs instance - /// @slow an extra O(N) per frame, could do this during eval - m_presetOutputs.customWaves = PresetOutputs::cwave_container(customWaves); - m_presetOutputs.customShapes = PresetOutputs::cshape_container(customShapes); - -} - -void Preset::initialize_PerPixelMeshes() -{ - - int x,y; - for (x=0;x::iterator pos = per_pixel_eqn_tree.begin(); - pos != per_pixel_eqn_tree.end(); ++pos) - pos->second->evaluate(mesh_x, mesh_y); - -} - -int Preset::readIn(std::istream & fs) { - - line_mode_t line_mode; - presetOutputs().compositeShader.programSource.clear(); - presetOutputs().warpShader.programSource.clear(); - - /* Parse any comments */ - if (Parser::parse_top_comment(fs) < 0) - { - if (PRESET_DEBUG) - std::cerr << "[Preset::readIn] no left bracket found..." << std::endl; - return PROJECTM_FAILURE; - } - - /* Parse the preset name and a left bracket */ - char tmp_name[MAX_TOKEN_SIZE]; - - if (Parser::parse_preset_name(fs, tmp_name) < 0) - { - std::cerr << "[Preset::readIn] loading of preset name failed" << std::endl; - return PROJECTM_ERROR; - } - - /// @note We ignore the preset name because [preset00] is just not so useful - - // Loop through each line in file, trying to succesfully parse the file. - // If a line does not parse correctly, keep trucking along to next line. - int retval; - while ((retval = Parser::parse_line(fs, this)) != EOF) - { - if (retval == PROJECTM_PARSE_ERROR) - { - line_mode = UNSET_LINE_MODE; - // std::cerr << "[Preset::readIn()] parse error in file \"" << this->absoluteFilePath() << "\"" << std::endl; - } - } - -// std::cerr << "loadPresetFile: finished line parsing successfully" << std::endl; - - /* Now the preset has been loaded. - Evaluation calls can be made at appropiate - times in the frame loop */ - -return PROJECTM_SUCCESS; -} - -/* loadPresetFile: private function that loads a specific preset denoted - by the given pathname */ -int Preset::loadPresetFile(const std::string & pathname) -{ - - - /* Open the file corresponding to pathname */ - std::ifstream fs(pathname.c_str()); - if (!fs || fs.eof()) { - if (PRESET_DEBUG) - std::cerr << "loadPresetFile: loading of file \"" << pathname << "\" failed!\n"; - return PROJECTM_ERROR; - } - - return readIn(fs); - -} diff --git a/src/libprojectM/Preset.hpp b/src/libprojectM/Preset.hpp index fb8df2701..4e8cd9d15 100644 --- a/src/libprojectM/Preset.hpp +++ b/src/libprojectM/Preset.hpp @@ -1,248 +1,38 @@ - -/** - * projectM -- Milkdrop-esque visualisation SDK - * Copyright (C)2003-2007 projectM Team +/* + * Preset.hpp * - * 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 - * - */ -/** - * $Id$ - * - * Preset - * - * $Log$ + * Created on: Aug 5, 2008 + * Author: carm */ -#ifndef _PRESET_HPP -#define _PRESET_HPP +#ifndef PRESET_HPP_ +#define PRESET_HPP_ -#include "Common.hpp" #include -#include -#include -#define PRESET_DEBUG 0 /* 0 for no debugging, 1 for normal, 2 for insane */ - -#include "CustomShape.hpp" -#include "CustomWave.hpp" -#include "Expr.hpp" -#include "PerPixelEqn.hpp" -#include "PerFrameEqn.hpp" -#include "BuiltinParams.hpp" -#include "PresetFrameIO.hpp" -#include "InitCond.hpp" - -class CustomWave; -class CustomShape; -class InitCond; - - -class Preset -{ -protected: +#include "BeatDetect.hpp" +#include "Pipeline.hpp" +#include "PipelineContext.hpp" +class Preset { public: + Preset(); + Preset(const std::string & name, const std::string & author); + virtual ~Preset(); - /// Load a preset by filename with input and output buffers specified. - /// \param absoluteFilePath the absolute file path of a preset to load from the file system - /// \param presetName a descriptive name for the preset. Usually just the file name - /// \param presetInputs a reference to read only projectM engine variables - /// \param presetOutputs initialized and filled with data parsed from a preset - Preset(const std::string & absoluteFilePath, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs); + void setName(const std::string & value); + const std::string & name() const; - /// Load a preset from an input stream with input and output buffers specified. - /// \param in an already initialized input stream to read the preset file from - /// \param presetName a descriptive name for the preset. Usually just the file name - /// \param presetInputs a reference to read only projectM engine variables - /// \param presetOutputs initialized and filled with data parsed from a preset - Preset(std::istream & in, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs); + void setAuthor(const std::string & value); + const std::string & author() const; - ~Preset(); - - /// Evaluates the preset for a frame given the current values of preset inputs / outputs - /// All calculated values are stored in the associated preset outputs instance - void evaluateFrame(); - - /// All "builtin" parameters for this preset. Anything *but* user defined parameters and - /// custom waves / shapes objects go here. - /// @bug encapsulate - BuiltinParams builtinParams; - - - /// Used by parser to find/create custom waves and shapes. May be refactored - template - static CustomObject * find_custom_object(int id, std::vector & customObjects); - - - int per_pixel_eqn_string_index; - int per_frame_eqn_string_index; - int per_frame_init_eqn_string_index; - - int per_frame_eqn_count, - per_frame_init_eqn_count; - - - /// Used by parser - /// @bug refactor - int add_per_pixel_eqn( char *name, GenExpr *gen_expr ); - - /// Accessor method to retrieve the absolute file path of the loaded preset - /// \returns a file path string - std::string absoluteFilePath() const - { - return m_absoluteFilePath; - } - - - /// Accessor method for the preset outputs instance associated with this preset - /// \returns A preset output instance with values computed from most recent evaluateFrame() - PresetOutputs & presetOutputs() const - { - - return m_presetOutputs; - } - - PresetInputs & presetInputs() const - { - - return m_presetInputs; - } - /// Sets the descriptive name for this preset (typically the file name) - /// \param theValue the new preset name to assign to the preset - void setPresetName ( const std::string& theValue ) - { - m_presetName = theValue; - } - - - /// Gets the descriptive name for this preset (typically the file name) - /// \returns the name of the preset - std::string presetName() const - { - return m_presetName; - } - - - /// @bug encapsulate - - PresetOutputs::cwave_container customWaves; - PresetOutputs::cshape_container customShapes; - - /// @bug encapsulate - /* Data structures that contain equation and initial condition information */ - std::vector per_frame_eqn_tree; /* per frame equations */ - std::map per_pixel_eqn_tree; /* per pixel equation tree */ - std::map per_frame_init_eqn_tree; /* per frame initial equations */ - std::map init_cond_tree; /* initial conditions */ - std::map user_param_tree; /* user parameter splay tree */ + virtual const Pipeline & pipeline() const = 0; + virtual void Render(const BeatDetect &music, const PipelineContext &context) = 0; private: - - // The absolute file path of the preset - std::string m_absoluteFilePath; - - // The absolute path of the preset - std::string m_absolutePath; - - // The name for the preset. Usually the file name, but in theory anything goes - std::string m_presetName; - - void initialize(const std::string & pathname); - void initialize(std::istream & in); - - int loadPresetFile(const std::string & pathname); - - void loadBuiltinParamsUnspecInitConds(); - void loadCustomWaveUnspecInitConds(); - void loadCustomShapeUnspecInitConds(); - - void evalCustomWavePerFrameEquations(); - void evalCustomShapePerFrameEquations(); - void evalPerFrameInitEquations(); - void evalCustomWaveInitConditions(); - void evalCustomShapeInitConditions(); - void evalPerPixelEqns(); - void evalPerFrameEquations(); - void initialize_PerPixelMeshes(); - int readIn(std::istream & fs); - - void preloadInitialize(); - void postloadInitialize(); - - PresetOutputs & m_presetOutputs; - PresetInputs & m_presetInputs; // added for gx, gy reference. - -template -void transfer_q_variables(std::vector & customObjects); + std::string _name; + std::string _author; }; - -template -void Preset::transfer_q_variables(std::vector & customObjects) -{ - CustomObject * custom_object; - - for (typename std::vector::iterator pos = customObjects.begin(); pos != customObjects.end();++pos) { - - custom_object = *pos; - custom_object->q1 = m_presetOutputs.q[0]; - custom_object->q2 = m_presetOutputs.q[1]; - custom_object->q3 = m_presetOutputs.q[2]; - custom_object->q4 = m_presetOutputs.q[3]; - custom_object->q5 = m_presetOutputs.q[4]; - custom_object->q6 = m_presetOutputs.q[5]; - custom_object->q7 = m_presetOutputs.q[6]; - custom_object->q8 = m_presetOutputs.q[7]; - } - - -} - -template -CustomObject * Preset::find_custom_object(int id, std::vector & customObjects) -{ - - CustomObject * custom_object = NULL; - - - for (typename std::vector::iterator pos = customObjects.begin(); pos != customObjects.end();++pos) { - if ((*pos)->id == id) { - custom_object = *pos; - break; - } - } - - if (custom_object == NULL) - { - - if ((custom_object = new CustomObject(id)) == NULL) - { - return NULL; - } - - customObjects.push_back(custom_object); - - } - - assert(custom_object); - return custom_object; -} - - - -#endif /** !_PRESET_HPP */ +#endif /* PRESET_HPP_ */