// // C++ Implementation: PresetLoader // // Description: // // // Author: Carmelo Piccione , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "PresetLoader.hpp" #include "Preset.hpp" #include "PresetFactory.hpp" #include #include #include #ifdef LINUX extern "C" { #include } #endif #ifdef MACOS extern "C" { #include } #endif #include #include "fatal.h" #include "Common.hpp" PresetLoader::PresetLoader (int gx, int gy, std::string dirname = std::string()) :_dirname ( dirname ), _dir ( 0 ) { _presetFactoryManager.initialize(gx,gy); // Do one scan if ( _dirname != std::string() ) rescan(); else clear(); } PresetLoader::~PresetLoader() { if ( _dir ) closedir ( _dir ); } void PresetLoader::setScanDirectory ( std::string dirname ) { _dirname = dirname; } void PresetLoader::rescan() { // std::cerr << "Rescanning..." << std::endl; // Clear the directory entry collection clear(); // If directory already opened, close it first if ( _dir ) { closedir ( _dir ); _dir = 0; } // Allocate a new a stream given the current directory name if ( ( _dir = opendir ( _dirname.c_str() ) ) == NULL ) { handleDirectoryError(); return; // no files loaded. _entries is empty } struct dirent * dir_entry; std::set alphaSortedFileSet; std::set alphaSortedPresetNameSet; while ( ( dir_entry = readdir ( _dir ) ) != NULL ) { if (dir_entry->d_name == 0) continue; std::ostringstream out; // Convert char * to friendly string std::string filename ( dir_entry->d_name ); // Verify extension is projectm or milkdrop if (!_presetFactoryManager.extensionHandled(parseExtension(filename))) continue; if ( filename.length() > 0 && filename[0] == '.' ) continue; // Create full path name out << _dirname << PATH_SEPARATOR << filename; // Add to our directory entry collection alphaSortedFileSet.insert ( out.str() ); alphaSortedPresetNameSet.insert ( filename ); // the directory entry struct is freed elsewhere } // Push all entries in order from the file set to the file entries member (which is an indexed vector) for ( std::set::iterator pos = alphaSortedFileSet.begin(); pos != alphaSortedFileSet.end();++pos ) _entries.push_back ( *pos ); // Push all preset names in similar fashion for ( std::set::iterator pos = alphaSortedPresetNameSet.begin(); pos != alphaSortedPresetNameSet.end();++pos ) _presetNames.push_back ( *pos ); // Give all presets equal rating of 3 - why 3? I don't know _ratings = std::vector(TOTAL_RATING_TYPES, RatingList( _presetNames.size(), 3 )); _ratingsSums = std::vector(TOTAL_RATING_TYPES, 3 * _presetNames.size()); assert ( _entries.size() == _presetNames.size() ); } std::unique_ptr PresetLoader::loadPreset ( unsigned int index ) const { // Check that index isn't insane assert ( index >= 0 ); assert ( index < _entries.size() ); // Return a new autopointer to a preset const std::string extension = parseExtension ( _entries[index] ); return _presetFactoryManager.factory(extension).allocate ( _entries[index], _presetNames[index] ); } std::unique_ptr PresetLoader::loadPreset ( const std::string & url ) const { // Return a new autopointer to a preset const std::string extension = parseExtension ( url ); /// @bug probably should not use url for preset name return _presetFactoryManager.factory(extension).allocate (url, url); } void PresetLoader::handleDirectoryError() { #ifdef WIN32 std::cerr << "[PresetLoader] warning: errno unsupported on win32 platforms. fix me" << std::endl; #else switch ( errno ) { case ENOENT: std::cerr << "[PresetLoader] ENOENT error. The path \"" << this->_dirname << "\" probably does not exist. \"man open\" for more info." << std::endl; break; case ENOMEM: std::cerr << "[PresetLoader] out of memory! Are you running Windows?" << std::endl; abort(); case ENOTDIR: std::cerr << "[PresetLoader] directory specified is not a preset directory! Trying to continue..." << std::endl; break; case ENFILE: std::cerr << "[PresetLoader] Your system has reached its open file limit. Trying to continue..." << std::endl; break; case EMFILE: std::cerr << "[PresetLoader] too many files in use by projectM! Bailing!" << std::endl; break; case EACCES: std::cerr << "[PresetLoader] permissions issue reading the specified preset directory." << std::endl; break; default: break; } #endif } void PresetLoader::setRating(unsigned int index, int rating, const PresetRatingType ratingType) { assert ( index >=0 ); const unsigned int ratingTypeIndex = static_cast(ratingType); assert (index < _ratings[ratingTypeIndex].size()); _ratingsSums[ratingTypeIndex] -= _ratings[ratingTypeIndex][index]; _ratings[ratingTypeIndex][index] = rating; _ratingsSums[ratingType] += rating; } unsigned int PresetLoader::addPresetURL ( const std::string & url, const std::string & presetName, const std::vector & ratings) { _entries.push_back(url); _presetNames.push_back ( presetName ); assert(ratings.size() == TOTAL_RATING_TYPES); assert(ratings.size() == _ratings.size()); for (int i = 0; i < _ratings.size(); i++) _ratings[i].push_back(ratings[i]); for (int i = 0; i < ratings.size(); i++) _ratingsSums[i] += ratings[i]; return _entries.size()-1; } void PresetLoader::removePreset ( unsigned int index ) { _entries.erase ( _entries.begin() + index ); _presetNames.erase ( _presetNames.begin() + index ); for (int i = 0; i < _ratingsSums.size(); i++) { _ratingsSums[i] -= _ratings[i][index]; _ratings[i].erase ( _ratings[i].begin() + index ); } } const std::string & PresetLoader::getPresetURL ( unsigned int index ) const { return _entries[index]; } const std::string & PresetLoader::getPresetName ( unsigned int index ) const { return _presetNames[index]; } int PresetLoader::getPresetRating ( unsigned int index, const PresetRatingType ratingType ) const { return _ratings[ratingType][index]; } const std::vector & PresetLoader::getPresetRatings () const { return _ratings; } const std::vector & PresetLoader::getPresetRatingsSums() const { return _ratingsSums; } void PresetLoader::setPresetName(unsigned int index, std::string name) { _presetNames[index] = name; } void PresetLoader::insertPresetURL ( unsigned int index, const std::string & url, const std::string & presetName, const RatingList & ratings) { _entries.insert ( _entries.begin() + index, url ); _presetNames.insert ( _presetNames.begin() + index, presetName ); for (int i = 0; i < _ratingsSums.size();i++) { _ratingsSums[i] += _ratings[i][index]; _ratings[i].insert ( _ratings[i].begin() + index, ratings[i] ); } assert ( _entries.size() == _presetNames.size() ); }