| // |
| // 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()); |
| } |