| // |
| // C++ Implementation: PresetLoader |
| // |
| // Description: |
| // |
| // |
| // Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2007 |
| // |
| // Copyright: See COPYING file that comes with this distribution |
| // |
| // |
| #include "PresetLoader.hpp" |
| #include "Preset.hpp" |
| #include "PresetFactory.hpp" |
| #include <iostream> |
| #include <sstream> |
| #include <set> |
| |
| #ifdef LINUX |
| extern "C" |
| { |
| #include <errno.h> |
| } |
| #endif |
| |
| #ifdef MACOS |
| extern "C" |
| { |
| #include <errno.h> |
| } |
| #endif |
| |
| #include <cassert> |
| #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<std::string> alphaSortedFileSet; |
| std::set<std::string> 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<std::string>::iterator pos = alphaSortedFileSet.begin(); |
| pos != alphaSortedFileSet.end();++pos ) |
| _entries.push_back ( *pos ); |
| |
| // Push all preset names in similar fashion |
| for ( std::set<std::string>::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<RatingList>(TOTAL_RATING_TYPES, RatingList( _presetNames.size(), 3 )); |
| _ratingsSums = std::vector<int>(TOTAL_RATING_TYPES, 3 * _presetNames.size()); |
| |
| |
| assert ( _entries.size() == _presetNames.size() ); |
| |
| |
| |
| } |
| |
| |
| std::auto_ptr<Preset> 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::auto_ptr<Preset> 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<unsigned int>(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<int> & 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<RatingList> & PresetLoader::getPresetRatings () const |
| { |
| return _ratings; |
| } |
| |
| const std::vector<int> & 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() ); |
| |
| |
| } |