From 3ea0067cafd284757654a07e46bcf54ad49ad650 Mon Sep 17 00:00:00 2001 From: w1z7ard Date: Mon, 2 Jul 2007 15:50:35 +0000 Subject: [PATCH] implementing portable directory scanner in preset loader git-svn-id: https://projectm.svn.sourceforge.net/svnroot/projectm/personal/carm/dev-1.0@228 6778bc44-b910-0410-a7a0-be141de4315d --- src/projectM-engine/PresetLoader.cpp | 74 +++- src/projectM-engine/PresetLoader.hpp | 45 ++- src/projectM-engine/PresetSwitcher.cpp | 448 +++++++++++++------------ src/projectM-engine/PresetSwitcher.hpp | 4 +- 4 files changed, 320 insertions(+), 251 deletions(-) diff --git a/src/projectM-engine/PresetLoader.cpp b/src/projectM-engine/PresetLoader.cpp index 4465f84c6..07373c3e9 100644 --- a/src/projectM-engine/PresetLoader.cpp +++ b/src/projectM-engine/PresetLoader.cpp @@ -11,19 +11,75 @@ // #include "PresetLoader.hpp" #include + extern "C" { #include +#include +#include + } PresetLoader::PresetLoader(std::string pathame) { - - // Initialize a directory watcher - #ifdef LINUX - if ((m_notifyFD = inotify_init()) == -1) { - std::cerr << "[PresetLoader] failed to initialize inotify instance (error " << errno << std::endl; - } - #endif - - } + +void PresetLoader::rescan() { + +// If directory already opened, close it first + if (m_dir) { + closedir(dir); + } + +// Allocate a new a stream given the current diectory name +if ((m_dir = opendir(m_dirname)) == NULL) { + handleDirectoryError(); +} + +std::string fullPath; +std::ostringstream out(fullPath); + +struct dirent * dir_entry; +while ((dir_entry = readdir(m_dir)) != NULL) { + + // Convert char * to friendly string + std::string filename(dir_entry->d_name); + + // Verify extension is projectm or milkdrop + if (filename.rfind(PROJECTM_FILE_EXTENSION) <= 0 + || filename.rfind(MILKDROP_FILE_EXTENSION) <= 0) + continue; + + // Create full path name + out << dirname << PATH_SEPARATOR << filename; + + // Save to our directory entry collcetion + m_entries.add(out.str()); + + // We can now toss out the directory entry struct + free(dir_entry); + +} + +} + + +void PresetLoader::handleDirectoryError() { + switch (errno) { + case ENOENT: + break; + case ENOMEM: + abort(); + case ENOTDIR: + break; + case ENFILE: + std::cerr << "[PresetLoader] Your system has reached its open file limit. Giving up..." << std::endl; + abort(); + case EMFILE: + std::cerr << "[PresetLoader] too many files in use by projectM! Bailing!" << std::endl; + abort(); + case EACCES: + break; + default: + break; + } +} \ No newline at end of file diff --git a/src/projectM-engine/PresetLoader.hpp b/src/projectM-engine/PresetLoader.hpp index 1ba5d636a..cafd9a064 100644 --- a/src/projectM-engine/PresetLoader.hpp +++ b/src/projectM-engine/PresetLoader.hpp @@ -15,6 +15,22 @@ class PresetLoader { public: + static const std::string PROJECTM_FILE_EXTENSION = ".prjm"; + static const std::string MILKDROP_FILE_EXTENSION = ".milk"; + + #ifdef LINUX + static const std::string PATH_SEPARTOR = "/"; + #endif + + #ifdef MACOS + static const std::string PATH_SEPARTOR = "/"; + #endif + + #ifdef WIN32 + static const std::string PATH_SEPARTOR = "\"; + #endif + + /** Initializes the preset loader with the target directory specified */ PresetLoader(std::string pathname); @@ -22,32 +38,27 @@ class PresetLoader { ~PresetLoader(); /** Load a preset by indexing the collection of presets from a directory */ + /** Autopointers: when you take it, I leave it */ auto_ptr loadPreset(unsigned int index); auto_ptr loadPreset(std::string filename); - - -// void unloadPreset(unsigned int index); -// void unloadPreset(Preset & preset); /** Returns the number of presets in the active directory */ - std::size_t getNumPresets(); - - + inline std::size_t getNumPresets() { + return m_entries.size(); + } + /** Sets the directory where the loader will search for files */ void setScanDirectory(std::string pathname); + + /** Rescans the active preset directory */ + void rescan(); - /** Clears the preset cache forceably. This cache gets larger on each prseset load- the user of - this class must manually flush out the buffer. - @idea boost shared pointers would be useful here! */ - void flushCache(); - + private: - int m_notifyFD; const std::string m_dirname; - StaticArray cachedPresets; - - - + int m_activeIndex; + DIR * m_dir; + std::vector m_entries; }; diff --git a/src/projectM-engine/PresetSwitcher.cpp b/src/projectM-engine/PresetSwitcher.cpp index ce4ebf94e..d06e6842b 100644 --- a/src/projectM-engine/PresetSwitcher.cpp +++ b/src/projectM-engine/PresetSwitcher.cpp @@ -1,7 +1,7 @@ // // C++ Implementation: PresetSwitcher // -// Description: +// Description: // // // Author: Carmelo Piccione , (C) 2007 @@ -14,60 +14,60 @@ int PresetSwitcher::destroyPresetLoader() { - //if ((Preset::active_preset != NULL) && (Preset::active_preset != Preset::idle_preset)) { - // Preset::active_preset->close_preset(); - //} + //if ((Preset::active_preset != NULL) && (Preset::active_preset != Preset::idle_preset)) { + // Preset::active_preset->close_preset(); + //} - ///Preset::active_preset = NULL; - //Preset::destroy_idle_preset(); - //destroy_builtin_param_db(); - //destroy_builtin_func_db(); - //Eval::destroy_infix_ops(); + ///Preset::active_preset = NULL; + //Preset::destroy_idle_preset(); + //destroy_builtin_param_db(); + //destroy_builtin_func_db(); + //Eval::destroy_infix_ops(); - return PROJECTM_SUCCESS; + return PROJECTM_SUCCESS; } /* Loads a specific preset by absolute path */ int PresetSwitcher::loadPresetByFile(char * filename) { - Preset * new_preset; - - /* Finally, load the preset using its actual path */ - if ((new_preset = Preset::load_preset(filename)) == NULL) { + Preset * new_preset; + + /* Finally, load the preset using its actual path */ + if ((new_preset = Preset::load_preset(filename)) == NULL) { #ifdef PRESET_DEBUG - printf("loadPresetByFile: failed to load preset!\n"); + printf("loadPresetByFile: failed to load preset!\n"); #endif - return PROJECTM_ERROR; - } -abort(); + return PROJECTM_ERROR; + } + abort(); - /* Closes a preset currently loaded, if any */ + /* Closes a preset currently loaded, if any */ // if ((this->activePreset != NULL) && (this->activePreset != Preset::idle_preset)) - // this->activePreset->close_preset(); + // this->activePreset->close_preset(); - /* Sets active preset global pointer */ - //this->activePreset = new_preset; + /* Sets active preset global pointer */ + //this->activePreset = new_preset; - /* Reinitialize engine variables */ + /* Reinitialize engine variables */ // PresetSwitcher_resetengine(); - - /* Add any missing initial conditions for each wave */ + + /* Add any missing initial conditions for each wave */ // this->activePreset->load_custom_wave_init_conditions(); - /* Add any missing initial conditions for each wave */ + /* Add any missing initial conditions for each wave */ // this->activePreset->load_custom_shape_init_conditions(); - /* Add any missing initial conditions */ + /* Add any missing initial conditions */ // load_init_conditions(); - - /* Need to do this once for menu */ - //this->activePreset->evalInitConditions(); - // evalPerFrameInitEquations(); + + /* Need to do this once for menu */ + //this->activePreset->evalInitConditions(); + // evalPerFrameInitEquations(); - return PROJECTM_SUCCESS; + return PROJECTM_SUCCESS; } @@ -77,52 +77,52 @@ abort(); int PresetSwitcher::switchPreset(switch_mode_t switch_mode, int cut_type) { - Preset * new_preset = 0; - - int switch_index; - int sindex = 0; - int slen = 0; + Preset * new_preset = 0; + + int switch_index; + int sindex = 0; + int slen = 0; DWRITE( "switchPreset(): in\n" ); // DWRITE( "switchPreset(): %s\n", presetURL ); - switch (switch_mode) { - case ALPHA_NEXT: + switch (switch_mode) { + case ALPHA_NEXT: // preset_index = switch_index = preset_index + 1; - break; - case ALPHA_PREVIOUS: + break; + case ALPHA_PREVIOUS: // preset_index = switch_index = preset_index - 1; - break; - case RANDOM_NEXT: - switch_index = rand(); - break; - case RESTART_ACTIVE: + break; + case RANDOM_NEXT: + switch_index = rand(); + break; + case RESTART_ACTIVE: // switch_index = preset_index; - break; - default: - return PROJECTM_FAILURE; - } + break; + default: + return PROJECTM_FAILURE; + } DWRITE( "switch_index: %d\n", switch_index ); - // iterate through the presetURL directory looking for the next entry - { - struct dirent** entries; + // iterate through the presetURL directory looking for the next entry + { + struct dirent** entries; // int dir_size = scandir(presetURL, &entries, /* is_valid_extension */ NULL, alphasort); // DWRITE( "dir_size: %d\n", dir_size ); // if (dir_size > 0) { - int i; + int i; // DWRITE( "nentries: %d\n", dir_size ); - + // switch_index %= dir_size; // if (switch_index < 0) switch_index += dir_size // for (i = 0; i < dir_size; ++i) { // if (switch_index == i) { - // matching entry + // matching entry // const size_t len = strlen(presetURL); // char* path = (char *) malloc(len + strlen(entries[i]->d_name) + 2); -// if (path) { +// if (path) { // strcpy(path, presetURL); // if (len && ((path[len - 1] != '/')||(path[len - 1] != '\\'))) { //#ifdef WIN32 @@ -132,10 +132,10 @@ int PresetSwitcher::switchPreset(switch_mode_t switch_mode, int cut_type) { //#endif // } // strcat(path + len, entries[i]->d_name); -// +// // new_preset = Preset::load_preset(path); // free(path); - + // // we must keep iterating to free the remaining entries // } // } @@ -143,252 +143,254 @@ int PresetSwitcher::switchPreset(switch_mode_t switch_mode, int cut_type) { // } // free(entries); // } - } + } #ifdef WIN32 new_preset = Preset::load_preset( "c:\\tmp\\PresetSwitcher-1.00\\presets_test\\C.milk" ); #else -// new_preset = Preset::load_preset( "/Users/descarte/tmp/PresetSwitcher-1.00/presets_test/B.milk" ); -// new_preset = NULL; + // new_preset = Preset::load_preset( "/Users/descarte/tmp/PresetSwitcher-1.00/presets_test/B.milk" ); + // new_preset = NULL; #endif - - if (!new_preset) { - return PROJECTM_ERROR; - } + + if (!new_preset) { + return PROJECTM_ERROR; + } - /* Closes a preset currently loaded, if any */ + /* Closes a preset currently loaded, if any */ // if ((this->activePreset != NULL) && (this->activePreset != Preset::idle_preset)) { - // this->activePreset->close_preset(); - // } + // this->activePreset->close_preset(); + // } - /* Sets global this->activePreset pointer */ - //this->activePreset = new_preset; + /* Sets global this->activePreset pointer */ + //this->activePreset = new_preset; #if 0 #ifndef PANTS - /** Split out the preset name from the path */ - slen = strlen( new_preset->file_path ); - sindex = slen; - while ( new_preset->file_path[sindex] != WIN32_PATH_SEPARATOR && - new_preset->file_path[sindex] != UNIX_PATH_SEPARATOR && sindex > 0 ) { - sindex--; - } - sindex++; - if ( presetName != NULL ) { - free( presetName ); - presetName = NULL; - } - presetName = (char *)wipemalloc( sizeof( char ) * (slen - sindex + 1) ); - strncpy( presetName, new_preset->file_path + sindex, slen - sindex ); - presetName[slen - sindex] = '\0'; + /** Split out the preset name from the path */ + slen = strlen( new_preset->file_path ); + sindex = slen; + while ( new_preset->file_path[sindex] != WIN32_PATH_SEPARATOR && + new_preset->file_path[sindex] != UNIX_PATH_SEPARATOR && sindex > 0 ) { + sindex--; + } + sindex++; + if ( presetName != NULL ) { + free( presetName ); + presetName = NULL; + } + presetName = (char *)wipemalloc( sizeof( char ) * (slen - sindex + 1) ); + strncpy( presetName, new_preset->file_path + sindex, slen - sindex ); + presetName[slen - sindex] = '\0'; #endif - /* Reinitialize the engine variables to sane defaults */ - PresetSwitcher_resetengine(); + /* Reinitialize the engine variables to sane defaults */ + PresetSwitcher_resetengine(); - /* Add any missing initial conditions */ - load_init_conditions(); + /* Add any missing initial conditions */ + load_init_conditions(); - /* Add any missing initial conditions for each wave */ - this->activePreset->load_custom_wave_init_conditions(); + /* Add any missing initial conditions for each wave */ + this->activePreset->load_custom_wave_init_conditions(); -/* Add any missing initial conditions for each shape */ - this->activePreset->load_custom_shape_init_conditions(); + /* Add any missing initial conditions for each shape */ + this->activePreset->load_custom_shape_init_conditions(); - /* Need to evaluate the initial conditions once */ - this->activePreset->evalInitConditions(); - this->activePreset->evalCustomWaveInitConditions(); - this->activePreset->evalCustomShapeInitConditions(); - // evalInitPerFrameEquations(); -#endif - return PROJECTM_SUCCESS; + /* Need to evaluate the initial conditions once */ + this->activePreset->evalInitConditions(); + this->activePreset->evalCustomWaveInitConditions(); + this->activePreset->evalCustomShapeInitConditions(); + // evalInitPerFrameEquations(); +#endif + return PROJECTM_SUCCESS; } int PresetSwitcher::switchPreset(switch_mode_t switch_mode, int cut_type) { - Preset * new_preset = 0; + Preset * new_preset = 0; - int switch_index; - int sindex = 0; - int slen = 0; + int switch_index; + int sindex = 0; + int slen = 0; DWRITE( "switchPreset(): in\n" ); DWRITE( "switchPreset(): %s\n", presetURL ); - switch (switch_mode) { - case ALPHA_NEXT: - preset_index = switch_index = preset_index + 1; - break; - case ALPHA_PREVIOUS: - preset_index = switch_index = preset_index - 1; - break; - case RANDOM_NEXT: - switch_index = rand(); - break; - case RESTART_ACTIVE: - switch_index = preset_index; - break; - default: - return PROJECTM_FAILURE; - } + switch (switch_mode) { + case ALPHA_NEXT: + preset_index = switch_index = preset_index + 1; + break; + case ALPHA_PREVIOUS: + preset_index = switch_index = preset_index - 1; + break; + case RANDOM_NEXT: + switch_index = rand(); + break; + case RESTART_ACTIVE: + switch_index = preset_index; + break; + default: + return PROJECTM_FAILURE; + } DWRITE( "switch_index: %d\n", switch_index ); - // iterate through the presetURL directory looking for the next entry - { - struct dirent** entries; - int dir_size = scandir(presetURL, &entries, /* is_valid_extension */ NULL, alphasort); + // iterate through the presetURL directory looking for the next entry + { + struct dirent** entries; + int dir_size = scandir(presetURL, &entries, /* is_valid_extension */ NULL, alphasort); DWRITE( "dir_size: %d\n", dir_size ); - if (dir_size > 0) { - int i; + if (dir_size > 0) { + int i; DWRITE( "nentries: %d\n", dir_size ); - switch_index %= dir_size; - if (switch_index < 0) switch_index += dir_size; - for (i = 0; i < dir_size; ++i) { - if (switch_index == i) { - // matching entry - const size_t len = strlen(presetURL); - char* path = (char *) malloc(len + strlen(entries[i]->d_name) + 2); - if (path) { - strcpy(path, presetURL); - if (len && ((path[len - 1] != '/')||(path[len - 1] != '\\'))) { + switch_index %= dir_size; + if (switch_index < 0) switch_index += dir_size; + for (i = 0; i < dir_size; ++i) { + if (switch_index == i) { + // matching entry + const size_t len = strlen(presetURL); + char* path = (char *) malloc(len + strlen(entries[i]->d_name) + 2); + if (path) { + strcpy(path, presetURL); + if (len && ((path[len - 1] != '/')||(path[len - 1] != '\\'))) { #ifdef WIN32 - strcat(path + len, "\\"); + strcat(path + len, "\\"); #else - strcat(path + len, "/"); + strcat(path + len, "/"); #endif - } - strcat(path + len, entries[i]->d_name); + } + strcat(path + len, entries[i]->d_name); - new_preset = Preset::load_preset(path); - free(path); + new_preset = Preset::load_preset(path); + free(path); - // we must keep iterating to free the remaining entries - } - } - free(entries[i]); - } - free(entries); - } - } + // we must keep iterating to free the remaining entries + } + } + free(entries[i]); + } + free(entries); + } + } #ifdef WIN32 new_preset = Preset::load_preset( "c:\\tmp\\projectM-1.00\\presets_test\\C.milk" ); #else -// new_preset = Preset::load_preset( "/Users/descarte/tmp/projectM-1.00/presets_test/B.milk" ); -// new_preset = NULL; + // new_preset = Preset::load_preset( "/Users/descarte/tmp/projectM-1.00/presets_test/B.milk" ); + // new_preset = NULL; #endif - if (!new_preset) { - switchToIdlePreset(); - return PROJECTM_ERROR; - } + if (!new_preset) { + switchToIdlePreset(); + return PROJECTM_ERROR; + } - /* Closes a preset currently loaded, if any */ - if ((Preset::active_preset != NULL) && (Preset::active_preset != Preset::idle_preset)) { + /* Closes a preset currently loaded, if any */ + if ((Preset::active_preset != NULL) && (Preset::active_preset != Preset::idle_preset)) { Preset::active_preset->close_preset(); } - /* Sets global Preset::active_preset pointer */ - Preset::active_preset = new_preset; + /* Sets global Preset::active_preset pointer */ + Preset::active_preset = new_preset; #ifndef PANTS - /** Split out the preset name from the path */ - slen = strlen( new_preset->file_path ); - sindex = slen; - while ( new_preset->file_path[sindex] != WIN32_PATH_SEPARATOR && - new_preset->file_path[sindex] != UNIX_PATH_SEPARATOR && sindex > 0 ) { - sindex--; - } - sindex++; - if ( presetName != NULL ) { - free( presetName ); - presetName = NULL; - } - presetName = (char *)wipemalloc( sizeof( char ) * (slen - sindex + 1) ); - strncpy( presetName, new_preset->file_path + sindex, slen - sindex ); - presetName[slen - sindex] = '\0'; + /** Split out the preset name from the path */ + slen = strlen( new_preset->file_path ); + sindex = slen; + while ( new_preset->file_path[sindex] != WIN32_PATH_SEPARATOR && + new_preset->file_path[sindex] != UNIX_PATH_SEPARATOR && sindex > 0 ) { + sindex--; + } + sindex++; + if ( presetName != NULL ) { + free( presetName ); + presetName = NULL; + } + presetName = (char *)wipemalloc( sizeof( char ) * (slen - sindex + 1) ); + strncpy( presetName, new_preset->file_path + sindex, slen - sindex ); + presetName[slen - sindex] = '\0'; #endif - /* Reinitialize the engine variables to sane defaults */ - projectM_resetengine(); + /* Reinitialize the engine variables to sane defaults */ + projectM_resetengine(); - /* Add any missing initial conditions */ - load_init_conditions(); + /* Add any missing initial conditions */ + load_init_conditions(); - /* Add any missing initial conditions for each wave */ - Preset::active_preset->load_custom_wave_init_conditions(); + /* Add any missing initial conditions for each wave */ + Preset::active_preset->load_custom_wave_init_conditions(); -/* Add any missing initial conditions for each shape */ - Preset::active_preset->load_custom_shape_init_conditions(); + /* Add any missing initial conditions for each shape */ + Preset::active_preset->load_custom_shape_init_conditions(); + + /* Need to evaluate the initial conditions once */ + Preset::active_preset->evalInitConditions(); + Preset::active_preset->evalCustomWaveInitConditions(); + Preset::active_preset->evalCustomShapeInitConditions(); + + // evalInitPerFrameEquations(); + return PROJECTM_SUCCESS; - /* Need to evaluate the initial conditions once */ - Preset::active_preset->evalInitConditions(); - Preset::active_preset->evalCustomWaveInitConditions(); - Preset::active_preset->evalCustomShapeInitConditions(); - // evalInitPerFrameEquations(); - return PROJECTM_SUCCESS; } /* Loads a specific preset by absolute path */ int projectM::loadPresetByFile(char * filename) { - Preset * new_preset; + Preset * new_preset; - /* Finally, load the preset using its actual path */ - if ((new_preset = Preset::load_preset(filename)) == NULL) { + /* Finally, load the preset using its actual path */ + if ((new_preset = Preset::load_preset(filename)) == NULL) { #ifdef PRESET_DEBUG - printf("loadPresetByFile: failed to load preset!\n"); + printf("loadPresetByFile: failed to load preset!\n"); #endif - return PROJECTM_ERROR; - } + return PROJECTM_ERROR; + } - /* Closes a preset currently loaded, if any */ - if ((Preset::active_preset != NULL) && (Preset::active_preset != Preset::idle_preset)) - Preset::active_preset->close_preset(); + /* Closes a preset currently loaded, if any */ + if ((Preset::active_preset != NULL) && (Preset::active_preset != Preset::idle_preset)) + Preset::active_preset->close_preset(); - /* Sets active preset global pointer */ - Preset::active_preset = new_preset; + /* Sets active preset global pointer */ + Preset::active_preset = new_preset; - /* Reinitialize engine variables */ - projectM_resetengine(); + /* Reinitialize engine variables */ + projectM_resetengine(); - /* Add any missing initial conditions for each wave */ - Preset::active_preset->load_custom_wave_init_conditions(); + /* Add any missing initial conditions for each wave */ + Preset::active_preset->load_custom_wave_init_conditions(); - /* Add any missing initial conditions for each wave */ - Preset::active_preset->load_custom_shape_init_conditions(); + /* Add any missing initial conditions for each wave */ + Preset::active_preset->load_custom_shape_init_conditions(); - /* Add any missing initial conditions */ - load_init_conditions(); + /* Add any missing initial conditions */ + load_init_conditions(); - /* Need to do this once for menu */ - Preset::active_preset->evalInitConditions(); - // evalPerFrameInitEquations(); + /* Need to do this once for menu */ + Preset::active_preset->evalInitConditions(); + // evalPerFrameInitEquations(); - return PROJECTM_SUCCESS; + return PROJECTM_SUCCESS; } /* Returns nonzero if string 'name' contains .milk or (the better) .prjm extension. Not a very strong function currently */ int PresetSwitcher::is_valid_extension(const struct dirent* ent) { - const char* ext = 0; - - if (!ent) return FALSE; - - ext = strrchr(ent->d_name, '.'); - if (!ext) ext = ent->d_name; - - if (0 == strcasecmp(ext, MILKDROP_FILE_EXTENSION)) return TRUE; - if (0 == strcasecmp(ext, PROJECTM_FILE_EXTENSION)) return TRUE; + const char* ext = 0; - return FALSE; + if (!ent) return FALSE; + + ext = strrchr(ent->d_name, '.'); + if (!ext) ext = ent->d_name; + + if (0 == strcasecmp(ext, MILKDROP_FILE_EXTENSION)) return TRUE; + if (0 == strcasecmp(ext, PROJECTM_FILE_EXTENSION)) return TRUE; + + return FALSE; } diff --git a/src/projectM-engine/PresetSwitcher.hpp b/src/projectM-engine/PresetSwitcher.hpp index 7ed36c85b..a0c4045d1 100644 --- a/src/projectM-engine/PresetSwitcher.hpp +++ b/src/projectM-engine/PresetSwitcher.hpp @@ -32,9 +32,9 @@ class PresetSwitcher { public: /** Preset switching */ - int loadPresetDir( char *dir ); + int loadPresetDir( char *dir ); int closePresetDir(); - int switchPreset( switch_mode_t switch_mode, int cut_type ); + int switchPreset( switch_mode_t switch_mode, int cut_type); int loadPresetByFile( char *filename ); int initPresetLoader(); int destroyPresetLoader();