diff --git a/src/projectM-engine/CMakeLists.txt b/src/projectM-engine/CMakeLists.txt index cde1f7d3c..0ab1c8fad 100644 --- a/src/projectM-engine/CMakeLists.txt +++ b/src/projectM-engine/CMakeLists.txt @@ -4,7 +4,7 @@ ADD_LIBRARY(projectM SHARED projectM.cpp projectM.hpp PBuffer.cpp PBuffer.hpp In Param.cpp CustomWave.cpp CustomShape.hpp CustomShape.cpp Param.hpp CustomWave.hpp BeatDetect.hpp console_interface.h Func.hpp Func.cpp Eval.cpp wipemalloc.h PerFrameEqn.cpp PerPointEqn.cpp fftsg.cpp console_interface.cpp CValue.hpp Expr.hpp timer.cpp wipemalloc.cpp PerFrameEqn.hpp PerPixelEqn.hpp PerPointEqn.hpp BuiltinFuncs.hpp -BuiltinFuncs.cpp compare.h event.h fatal.h fftsg.h timer.h BuiltinParams.hpp BuiltinParams.cpp Preset.hpp Renderer.cpp Renderer.hpp ParamUtils.hpp PresetLoader.cpp PresetLoader.hpp PresetChooser.hpp PresetChooser.cpp PresetFrameIO.cpp PresetFrameIO.hpp PresetMerge.cpp PresetMerge.hpp ConfigFile.h ConfigFile.cpp) +BuiltinFuncs.cpp compare.h event.h fatal.h fftsg.h timer.h BuiltinParams.hpp BuiltinParams.cpp Preset.hpp Renderer.cpp Renderer.hpp ParamUtils.hpp PresetLoader.cpp PresetLoader.hpp PresetChooser.hpp PresetChooser.cpp PresetFrameIO.cpp PresetFrameIO.hpp PresetMerge.cpp PresetMerge.hpp ConfigFile.h ConfigFile.cpp IdlePreset.hpp IdlePreset.cpp) OPTION(USE_FTGL "Use FTGL for on-screen fonts" ON) diff --git a/src/projectM-engine/Parser.cpp b/src/projectM-engine/Parser.cpp index 27ee3a9be..a4df2ad72 100755 --- a/src/projectM-engine/Parser.cpp +++ b/src/projectM-engine/Parser.cpp @@ -45,6 +45,7 @@ #include "ParamUtils.hpp" #include "wipemalloc.h" +#include /* Grabs the next token from the file. The second argument points to the raw string */ @@ -62,7 +63,7 @@ int Parser::last_custom_shape_id; char Parser::last_eqn_type[MAX_TOKEN_SIZE]; int Parser::last_token_size; -token_t Parser::parseToken(FILE * fs, char * string) { +token_t Parser::parseToken(std::istream & fs, char * string) { char c; int i; @@ -70,14 +71,21 @@ token_t Parser::parseToken(FILE * fs, char * string) { if (string != NULL) memset(string, 0, MAX_TOKEN_SIZE); + /* Loop until a delimiter is found, or the maximum string size is found */ for (i = 0; i < MAX_TOKEN_SIZE;i++) { - c = fgetc(fs); + //c = fgetc(fs); + if (!fs || fs.eof()) + c = EOF; + else + c = fs.get(); + + std::cerr << c; last_token_size++; /* If the string line buffer is full, quit */ if (string_line_buffer_index == (STRING_LINE_SIZE - 1)) return tStringBufferFilled; - + /* Otherwise add this character to the string line buffer */ string_line_buffer[string_line_buffer_index++] = c; /* Now interpret the character */ @@ -92,9 +100,16 @@ token_t Parser::parseToken(FILE * fs, char * string) { case '/': /* check for line comment here */ - if ((c = fgetc(fs)) == '/') { - while(1) { - c = fgetc(fs); + if (!fs || fs.eof()) + c = EOF; + else + c = fs.get(); + if (c == '/') { + while (true) { + if (!fs || fs.eof()) + c= EOF; + else + c = fs.get(); if (c == EOF) { line_mode = NORMAL_LINE_MODE; return tEOF; @@ -108,7 +123,7 @@ token_t Parser::parseToken(FILE * fs, char * string) { } /* Otherwise, just a regular division operator */ - ungetc(c, fs); + fs.unget(); return tDiv; case '*': @@ -158,7 +173,7 @@ token_t Parser::parseToken(FILE * fs, char * string) { /* Parse input in the form of "exp, exp, exp, ...)" Returns a general expression list */ -GenExpr **Parser::parse_prefix_args(FILE * fs, int num_args, Preset * preset) { +GenExpr **Parser::parse_prefix_args(std::istream & fs, int num_args, Preset * preset) { int i, j; GenExpr ** expr_list; /* List of arguments to function */ @@ -195,7 +210,7 @@ GenExpr **Parser::parse_prefix_args(FILE * fs, int num_args, Preset * preset) { } /* Parses a comment at the top of the file. Stops when left bracket is found */ -int Parser::parse_top_comment(FILE * fs) { +int Parser::parse_top_comment(std::istream & fs) { char string[MAX_TOKEN_SIZE]; token_t token; @@ -212,7 +227,7 @@ int Parser::parse_top_comment(FILE * fs) { /* Right Bracket is parsed by this function. puts a new string into name */ -int Parser::parse_preset_name(FILE * fs, char * name) { +int Parser::parse_preset_name(std::istream & fs, char * name) { token_t token; @@ -231,7 +246,7 @@ int Parser::parse_preset_name(FILE * fs, char * name) { /* Parses per pixel equations */ -int Parser::parse_per_pixel_eqn(FILE * fs, Preset * preset, char * init_string) { +int Parser::parse_per_pixel_eqn(std::istream & fs, Preset * preset, char * init_string) { char string[MAX_TOKEN_SIZE]; @@ -276,7 +291,7 @@ if (init_string != 0) { } /* Parses an equation line, this function is way too big, should add some helper functions */ -int Parser::parse_line(FILE * fs, Preset * preset) { +int Parser::parse_line(std::istream & fs, Preset * preset) { char eqn_string[MAX_TOKEN_SIZE]; token_t token; @@ -558,7 +573,7 @@ int Parser::parse_line(FILE * fs, Preset * preset) { /* Parses a general expression, this function is the meat of the parser */ -GenExpr * Parser::parse_gen_expr ( FILE * fs, TreeExpr * tree_expr, Preset * preset) { +GenExpr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, Preset * preset) { int i; char string[MAX_TOKEN_SIZE]; @@ -968,7 +983,7 @@ int Parser::insert_infix_rec(InfixOp * infix_op, TreeExpr * root) { } /* Parses an infix operator */ -GenExpr * Parser::parse_infix_op(FILE * fs, token_t token, TreeExpr * tree_expr, Preset * preset) { +GenExpr * Parser::parse_infix_op(std::istream & fs, token_t token, TreeExpr * tree_expr, Preset * preset) { GenExpr * gen_expr; @@ -1023,7 +1038,7 @@ GenExpr * Parser::parse_infix_op(FILE * fs, token_t token, TreeExpr * tree_expr, } /* Parses an integer, checks for +/- prefix */ -int Parser::parse_int(FILE * fs, int * int_ptr) { +int Parser::parse_int(std::istream & fs, int * int_ptr) { char string[MAX_TOKEN_SIZE]; token_t token; @@ -1091,7 +1106,7 @@ int Parser::string_to_float(char * string, float * float_ptr) { } /* Parses a floating point number */ -int Parser::parse_float(FILE * fs, float * float_ptr) { +int Parser::parse_float(std::istream & fs, float * float_ptr) { char string[MAX_TOKEN_SIZE]; char ** error_ptr; @@ -1140,7 +1155,7 @@ int Parser::parse_float(FILE * fs, float * float_ptr) { } /* Parses a per frame equation. That is, interprets a stream of data as a per frame equation */ -PerFrameEqn * Parser::parse_per_frame_eqn(FILE * fs, int index, Preset * preset) { +PerFrameEqn * Parser::parse_per_frame_eqn(std::istream & fs, int index, Preset * preset) { char string[MAX_TOKEN_SIZE]; Param * param; @@ -1184,7 +1199,7 @@ PerFrameEqn * Parser::parse_per_frame_eqn(FILE * fs, int index, Preset * preset) } /* Parses an 'implicit' per frame equation. That is, interprets a stream of data as a per frame equation without a prefix */ -PerFrameEqn * Parser::parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, Preset * preset) { +PerFrameEqn * Parser::parse_implicit_per_frame_eqn(std::istream & fs, char * param_string, int index, Preset * preset) { Param * param; PerFrameEqn * per_frame_eqn; @@ -1232,7 +1247,7 @@ PerFrameEqn * Parser::parse_implicit_per_frame_eqn(FILE * fs, char * param_strin } /* Parses an initial condition */ -InitCond * Parser::parse_init_cond(FILE * fs, char * name, Preset * preset) { +InitCond * Parser::parse_init_cond(std::istream & fs, char * name, Preset * preset) { Param * param; CValue init_val; @@ -1293,7 +1308,7 @@ InitCond * Parser::parse_init_cond(FILE * fs, char * name, Preset * preset) { } /* Parses a per frame init equation, not sure if this works right now */ -InitCond * Parser::parse_per_frame_init_eqn(FILE * fs, Preset * preset, std::map * database) { +InitCond * Parser::parse_per_frame_init_eqn(std::istream & fs, Preset * preset, std::map * database) { char name[MAX_TOKEN_SIZE]; Param * param = NULL; @@ -1374,7 +1389,7 @@ InitCond * Parser::parse_per_frame_init_eqn(FILE * fs, Preset * preset, std::map return init_cond; } -int Parser::parse_wavecode(char * token, FILE * fs, Preset * preset) { +int Parser::parse_wavecode(char * token, std::istream & fs, Preset * preset) { char * var_string; InitCond * init_cond; @@ -1452,7 +1467,7 @@ int Parser::parse_wavecode(char * token, FILE * fs, Preset * preset) { return PROJECTM_SUCCESS; } -int Parser::parse_shapecode(char * token, FILE * fs, Preset * preset) { +int Parser::parse_shapecode(char * token, std::istream & fs, Preset * preset) { char * var_string; InitCond * init_cond; @@ -1700,7 +1715,7 @@ int Parser::parse_shape_prefix(char * token, int * id, char ** eqn_string) { } /* Parses custom wave equations */ -int Parser::parse_wave(char * token, FILE * fs, Preset * preset) { +int Parser::parse_wave(char * token, std::istream & fs, Preset * preset) { int id; char * eqn_type; @@ -1726,7 +1741,7 @@ int Parser::parse_wave(char * token, FILE * fs, Preset * preset) { } -int Parser::parse_wave_helper(FILE * fs, Preset * preset, int id, char * eqn_type, char * init_string) { +int Parser::parse_wave_helper(std::istream & fs, Preset * preset, int id, char * eqn_type, char * init_string) { Param * param; GenExpr * gen_expr; @@ -1873,7 +1888,7 @@ int Parser::parse_wave_helper(FILE * fs, Preset * preset, int id, char * eqn_ty } /* Parses custom shape equations */ -int Parser::parse_shape(char * token, FILE * fs, Preset * preset) { +int Parser::parse_shape(char * token, std::istream & fs, Preset * preset) { int id; char * eqn_type; @@ -2003,7 +2018,7 @@ int Parser::get_string_prefix_len(char * string) { return i; } -int Parser::parse_shape_per_frame_init_eqn(FILE * fs, CustomShape * custom_shape, Preset * preset) { +int Parser::parse_shape_per_frame_init_eqn(std::istream & fs, CustomShape * custom_shape, Preset * preset) { InitCond * init_cond; if (PARSE_DEBUG) printf("parse_shape (per frame init): [begin] (LINE %d)\n", line_count); @@ -2024,7 +2039,7 @@ int Parser::parse_shape_per_frame_init_eqn(FILE * fs, CustomShape * custom_shape return PROJECTM_SUCCESS; } -int Parser::parse_shape_per_frame_eqn(FILE * fs, CustomShape * custom_shape, Preset * preset) { +int Parser::parse_shape_per_frame_eqn(std::istream & fs, CustomShape * custom_shape, Preset * preset) { Param * param; GenExpr * gen_expr; @@ -2084,7 +2099,7 @@ if (PARSE_DEBUG) printf("parse_shape (per_frame): [start] (custom shape id = %d) return PROJECTM_SUCCESS; } -int Parser::parse_wave_per_frame_eqn(FILE * fs, CustomWave * custom_wave, Preset * preset) { +int Parser::parse_wave_per_frame_eqn(std::istream & fs, CustomWave * custom_wave, Preset * preset) { Param * param; GenExpr * gen_expr; diff --git a/src/projectM-engine/Parser.hpp b/src/projectM-engine/Parser.hpp index 4b86e3fe1..75d83837d 100755 --- a/src/projectM-engine/Parser.hpp +++ b/src/projectM-engine/Parser.hpp @@ -29,7 +29,7 @@ #ifndef _PARSER_H #define _PARSER_H -#define PARSE_DEBUG 0 +#define PARSE_DEBUG 2 //#define PARSE_DEBUG 0 #include @@ -135,45 +135,45 @@ public: static char last_eqn_type[MAX_TOKEN_SIZE]; static int last_token_size; - static PerFrameEqn *parse_per_frame_eqn( FILE * fs, int index, + static PerFrameEqn *parse_per_frame_eqn( std::istream & fs, int index, Preset * preset); - static int parse_per_pixel_eqn( FILE * fs, Preset * preset, + static int parse_per_pixel_eqn( std::istream & fs, Preset * preset, char * init_string); - static InitCond *parse_init_cond( FILE * fs, char * name, Preset * preset ); - static int parse_preset_name( FILE * fs, char * name ); - static int parse_top_comment( FILE * fs ); - static int parse_line( FILE * fs, Preset * preset ); + static InitCond *parse_init_cond( std::istream & fs, char * name, Preset * preset ); + static int parse_preset_name( std::istream & fs, char * name ); + static int parse_top_comment( std::istream & fs ); + static int parse_line( std::istream & fs, Preset * preset ); static int get_string_prefix_len(char * string); static TreeExpr * insert_gen_expr(GenExpr * gen_expr, TreeExpr ** root); static TreeExpr * insert_infix_op(InfixOp * infix_op, TreeExpr ** root); - static token_t parseToken(FILE * fs, char * string); - static GenExpr ** parse_prefix_args(FILE * fs, int num_args, Preset * preset); - static GenExpr * parse_infix_op(FILE * fs, token_t token, TreeExpr * tree_expr, Preset * preset); - static GenExpr * parse_sign_arg(FILE * fs); - static int parse_float(FILE * fs, float * float_ptr); - static int parse_int(FILE * fs, int * int_ptr); + static token_t parseToken(std::istream & fs, char * string); + static GenExpr ** parse_prefix_args(std::istream & fs, int num_args, Preset * preset); + static GenExpr * parse_infix_op(std::istream & fs, token_t token, TreeExpr * tree_expr, Preset * preset); + static GenExpr * parse_sign_arg(std::istream & fs); + static int parse_float(std::istream & fs, float * float_ptr); + static int parse_int(std::istream & fs, int * int_ptr); static int insert_gen_rec(GenExpr * gen_expr, TreeExpr * root); static int insert_infix_rec(InfixOp * infix_op, TreeExpr * root); - static GenExpr * parse_gen_expr(FILE * fs, TreeExpr * tree_expr, Preset * preset); - static PerFrameEqn * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, Preset * preset); - static InitCond * parse_per_frame_init_eqn(FILE * fs, Preset * preset, std::map * database); + static GenExpr * parse_gen_expr(std::istream & fs, TreeExpr * tree_expr, Preset * preset); + static PerFrameEqn * parse_implicit_per_frame_eqn(std::istream & fs, char * param_string, int index, Preset * preset); + static InitCond * parse_per_frame_init_eqn(std::istream & fs, Preset * preset, std::map * database); static int parse_wavecode_prefix(char * token, int * id, char ** var_string); - static int parse_wavecode(char * token, FILE * fs, Preset * preset); + static int parse_wavecode(char * token, std::istream & fs, Preset * preset); static int parse_wave_prefix(char * token, int * id, char ** eqn_string); - static int parse_wave_helper(FILE * fs, Preset * preset, int id, char * eqn_type, char * init_string); - static int parse_shapecode(char * eqn_string, FILE * fs, Preset * preset); + static int parse_wave_helper(std::istream & fs, Preset * preset, int id, char * eqn_type, char * init_string); + static int parse_shapecode(char * eqn_string, std::istream & fs, Preset * preset); static int parse_shapecode_prefix(char * token, int * id, char ** var_string); - static int parse_wave(char * eqn_string, FILE * fs, Preset * preset); - static int parse_shape(char * eqn_string, FILE * fs, Preset * preset); + static int parse_wave(char * eqn_string, std::istream & fs, Preset * preset); + static int parse_shape(char * eqn_string, std::istream & fs, Preset * preset); static int parse_shape_prefix(char * token, int * id, char ** eqn_string); static int update_string_buffer(char * buffer, int * index); static int string_to_float(char * string, float * float_ptr); - static int parse_shape_per_frame_init_eqn(FILE * fs, CustomShape * custom_shape, Preset * preset); - static int parse_shape_per_frame_eqn(FILE * fs, CustomShape * custom_shape, Preset * preset); - static int parse_wave_per_frame_eqn(FILE * fs, CustomWave * custom_wave, Preset * preset); + static int parse_shape_per_frame_init_eqn(std::istream & fs, CustomShape * custom_shape, Preset * preset); + static int parse_shape_per_frame_eqn(std::istream & fs, CustomShape * custom_shape, Preset * preset); + static int parse_wave_per_frame_eqn(std::istream & fs, CustomWave * custom_wave, Preset * preset); }; #endif /** !_PARSER_H */ diff --git a/src/projectM-engine/Preset.cpp b/src/projectM-engine/Preset.cpp index c88eb3b17..3388e39e6 100755 --- a/src/projectM-engine/Preset.cpp +++ b/src/projectM-engine/Preset.cpp @@ -35,6 +35,23 @@ #include "InitCondUtils.hpp" #include "fatal.h" #include +#include + + +Preset::Preset(std::istream & in, const PresetInputs & presetInputs, PresetOutputs & presetOutputs): + builtinParams(presetInputs, presetOutputs), + file_path("[Input Stream]"), + m_presetOutputs(presetOutputs) +{ + + m_presetOutputs.customWaves.clear(); + m_presetOutputs.customShapes.clear(); + clearMeshChecks(); + + initialize(in); + +} + Preset::Preset(const std::string & filename, const PresetInputs & presetInputs, PresetOutputs & presetOutputs): builtinParams(presetInputs, presetOutputs), @@ -237,17 +254,15 @@ void Preset::evalPerFrameEquations() } - -void Preset::initialize(const std::string & pathname) -{ - +void Preset::preloadInitialize() { + + /// @note commented this out because it should be unnecessary // Clear equation trees - /// @slow unnecessary if we ensure this method is private - init_cond_tree.clear(); - user_param_tree.clear(); - per_frame_eqn_tree.clear(); - per_pixel_eqn_tree.clear(); - per_frame_init_eqn_tree.clear(); + //init_cond_tree.clear(); + //user_param_tree.clear(); + //per_frame_eqn_tree.clear(); + //per_pixel_eqn_tree.clear(); + //per_frame_init_eqn_tree.clear(); /* Set initial index values */ this->per_pixel_eqn_string_index = 0; @@ -259,20 +274,9 @@ void Preset::initialize(const std::string & pathname) memset(this->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE); memset(this->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE); memset(this->per_frame_init_eqn_string_buffer, 0, STRING_BUFFER_SIZE); - int retval; +} - std::cerr << "[Preset] loading file \"" << pathname << "\"..." << std::endl; - - if ((retval = loadPresetFile(pathname)) < 0) - { - - - std::cerr << "[Preset] failed to load file \"" << - pathname << "\"!" << std::endl; - - /// @bug how should we handle this problem? a well define exception? - throw retval; - } +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; @@ -281,8 +285,46 @@ void Preset::initialize(const std::string & pathname) this->loadBuiltinParamsUnspecInitConds(); this->loadCustomWaveUnspecInitConds(); this->loadCustomShapeUnspecInitConds(); + } +void Preset::initialize(const std::string & pathname) +{ + int retval; + + preloadInitialize(); + std::cerr << "[Preset] loading file \"" << pathname << "\"..." << std::endl; + + if ((retval = loadPresetFile(pathname)) < 0) + { + + 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) + { + + 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() { @@ -347,36 +389,16 @@ void Preset::evalPerPixelEqns() } -/* loadPresetFile: private function that loads a specific preset denoted - by the given pathname */ -int Preset::loadPresetFile(std::string pathname) -{ +int Preset::readIn(std::istream & fs) { + + - FILE * fs; - int retval; - int lineno; line_mode_t line_mode; - /* Open the file corresponding to pathname */ - if ((fs = fopen(pathname.c_str(), "rb")) == 0) - { -#if defined(PRESET_DEBUG) && defined(DEBUG) - DWRITE( "loadPresetFile: loading of file %s failed!\n", pathname); -#endif - return PROJECTM_ERROR; - } - -#if defined(PRESET_DEBUG) && defined(DEBUG) - DWRITE( "loadPresetFile: file stream \"%s\" opened successfully\n", pathname); -#endif - /* Parse any comments */ if (Parser::parse_top_comment(fs) < 0) { -#if defined(PRESET_DEBUG) && defined(DEBUG) - DWRITE( "loadPresetFile: no left bracket found...\n"); -#endif - fclose(fs); + std::cerr << "[Preset::readIn] no left bracket found..." << std::endl; return PROJECTM_FAILURE; } @@ -385,48 +407,54 @@ int Preset::loadPresetFile(std::string pathname) if (Parser::parse_preset_name(fs, tmp_name) < 0) { -#if defined(PRESET_DEBUG) && defined(DEBUG) - DWRITE( "loadPresetFile: loading of preset name in file \"%s\" failed\n", pathname); -#endif - fclose(fs); + std::cerr << "[Preset::readIn] loading of preset name failed" << std::endl; return PROJECTM_ERROR; } - name = std::string(tmp_name); -#if defined(PRESET_DEBUG) && defined(DEBUG) - DWRITE( "loadPresetFile: preset \"%s\" parsed\n", this->name); -#endif + this->name = std::string(tmp_name); - /* Parse each line until end of file */ - lineno = 0; -#if defined(PRESET_DEBUG) && defined(DEBUG) - DWRITE( "loadPresetFile: beginning line parsing...\n"); -#endif + std::cerr << "[Preset::readIn] preset \"" << this->name << "\" parsed." << std::endl;; + + // Start line counter at zero + int lineno = 0; + + // 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 = NORMAL_LINE_MODE; -#if defined(PRESET_DEBUG) && defined(DEBUG) - DWRITE( "loadPresetFile: parse error in file \"%s\": line %d\n", pathname,lineno); -#endif - + std::cerr << "[Preset::readIn()] parse error in file \"" << this->absoluteFilePath() << "\": line " << lineno << std::endl; } lineno++; } -#if defined(PRESET_DEBUG) && defined(DEBUG) - DWRITE("loadPresetFile: finished line parsing successfully\n"); -#endif + 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 */ - fclose(fs); -#if defined(PRESET_DEBUG) && defined(DEBUG) - DWRITE("loadPresetFile: file \"%s\" closed, preset ready\n", pathname); -#endif - return PROJECTM_SUCCESS; +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/projectM-engine/Preset.hpp b/src/projectM-engine/Preset.hpp index e93cfdc18..ceac9b84a 100644 --- a/src/projectM-engine/Preset.hpp +++ b/src/projectM-engine/Preset.hpp @@ -55,7 +55,6 @@ class Preset { protected: - public: @@ -66,6 +65,13 @@ public: /// \param presetOutputs initialized and filled with data parsed from a preset Preset(const std::string & filename, const PresetInputs & presetInputs, PresetOutputs & presetOutputs); + /// Load a preset from a stream with input and output buffers specified. + /// This is the only proper way to allocate a new preset. + /// \param in an already initialized input stream to read the preset file from + /// \param presetInputs a const reference to read only projectM engine variables + /// \param presetOutputs initialized and filled with data parsed from a preset + Preset(std::istream & in, const PresetInputs & presetInputs, PresetOutputs & presetOutputs); + ~Preset(); /// Evaluates the preset for a frame given the current values of preset inputs / outputs @@ -84,7 +90,7 @@ public: 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; @@ -132,7 +138,9 @@ private: std::string file_path; void initialize(const std::string & pathname); - int loadPresetFile(std::string pathname); + void initialize(std::istream & in); + + int loadPresetFile(const std::string & pathname); void loadBuiltinParamsUnspecInitConds(); void loadCustomWaveUnspecInitConds(); @@ -145,9 +153,11 @@ private: void evalCustomShapeInitConditions(); void evalPerPixelEqns(); void evalPerFrameEquations(); - + int readIn(std::istream & fs); inline void clearMeshChecks(); + void preloadInitialize(); + void postloadInitialize(); PresetOutputs & m_presetOutputs; diff --git a/src/projectM-engine/console_interface.cpp b/src/projectM-engine/console_interface.cpp index e87413981..34eccc115 100755 --- a/src/projectM-engine/console_interface.cpp +++ b/src/projectM-engine/console_interface.cpp @@ -117,7 +117,7 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode case PROJECTM_K_F1: renderer->showhelp++; renderer->showstats=0; - renderer->showfps=0; + renderer->showfps=0; break; case PROJECTM_K_F5: if(renderer->showhelp%2==0) renderer->showfps++; @@ -159,11 +159,15 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode break; case PROJECTM_K_n: - // paranoia but could be useful if directory is empty - if ((*m_presetPos == m_presetChooser->end())) + if (m_presetChooser->empty()) break; - ++(*m_presetPos); + // Case: idle preset currently running, selected first preset of chooser + else if (*m_presetPos == m_presetChooser->end()) { + (*m_presetPos = m_presetChooser->begin()); + } + else + ++(*m_presetPos); // Case: already at last preset, loop to beginning if (((*m_presetPos) == m_presetChooser->end())) { @@ -191,12 +195,20 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode smoothFrame = 0; break; case PROJECTM_K_p: + if (m_presetChooser->empty()) break; - if (*m_presetPos != m_presetChooser->begin()) { + // Case: idle preset currently running, selected last preset of chooser + else if (*m_presetPos == m_presetChooser->end()) { + --(*m_presetPos); + } + + else if (*m_presetPos != m_presetChooser->begin()) { --(*m_presetPos); - } else { + } + + else { *m_presetPos = m_presetChooser->end(); --(*m_presetPos); } diff --git a/src/projectM-engine/projectM.cpp b/src/projectM-engine/projectM.cpp index 9aaf6fddf..94e7d856b 100755 --- a/src/projectM-engine/projectM.cpp +++ b/src/projectM-engine/projectM.cpp @@ -47,6 +47,8 @@ #include "PCM.hpp" //Sound data handler (buffering, FFT, etc.) #include "CustomWave.hpp" #include "CustomShape.hpp" +#include "IdlePreset.hpp" + #include #include "Renderer.hpp" @@ -832,23 +834,23 @@ int projectM::initPresetTools() // Start the iterator m_presetPos = new PresetIterator(); - *m_presetPos = m_presetChooser->begin(); + + // Start at end ptr- this allows next/previous to easily be done from this position. + *m_presetPos = m_presetChooser->end(); + + // Load idle preset + std::cerr << "[projectM] Allocating idle preset..." << std::endl; + m_activePreset = IdlePreset::allocate(presetInputs, presetOutputs); // Case where no valid presets exist in directory - if ( *m_presetPos == m_presetChooser->end() ) + if (m_presetChooser->empty()) { - std::cerr << "[projectM] error: no valid files found in preset directory \"" - << PROJECTM_PRESET_PATH << "\"" << std::endl; - - /// @bug handle this better, load builtin preset perhaps - abort(); + std::cerr << "[projectM] warning: no valid files found in preset directory \"" + << PROJECTM_PRESET_PATH << "\"" << std::endl; } - // First preset - std::cerr << "[projectM] Allocating first preset..." << std::endl; - m_activePreset = m_presetPos->allocate ( presetInputs, presetOutputs ); -// m_activePreset2 = m_p - std::cerr << "[projectM] First preset allocated. File path is \"" << m_activePreset->absoluteFilePath() << "\"" << std::endl; + std::cerr << "[projectM] Idle preset allocated." << std::endl; + projectM_resetengine(); return PROJECTM_SUCCESS;