blob: 1542db32f2ae6ad7fee9d4052257e1814f218a99 [file] [log] [blame]
//
// 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());
}