mirror of
https://github.com/projectM-visualizer/projectm.git
synced 2026-02-06 18:45:43 +00:00
Preset subdirs (#385)
Scanning textures/presets dirs for textures and scanning preset dir for presets. Scanning is now done recursively, so presets and textures can be organized into subdirectories instead of needing to be flattened into a single directory. On POSIX systems makes use of [ftw](https://linux.die.net/man/3/ftw) which should be relatively efficient. Otherwise falls back to recursing with `dirent` (for windows). Probably should have made an autoconf check for `ftw` instead of doing `#ifdef WIN32`. * Scan subdirectories in presets directory * remove preset subdir config * Recursively scan for textures too, add c++-17 compatibility * Refactor directory scanning code so it's reused by texture loader and preset loader. Make cross-platform (maybe) * filescanner in makefile * extension filter for file loader * make extensions match up' * need string.h * Add FileScanner.cpp to win build (maybe) * scan all dirs * #ifndef #ifdef is def fun * bogus comment * bleh * bleh * itunes plugin with c++17 * EyeTunes needs to know about the FileScanner Co-authored-by: milkdropper.com <milkdropper.com@gmail.com> Co-authored-by: milkdropper <59471060+milkdropper@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
e51b2c7d63
commit
e49720ecfa
@ -15,29 +15,19 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
|
||||
#ifdef __unix__
|
||||
extern "C"
|
||||
{
|
||||
#include <errno.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
extern "C"
|
||||
{
|
||||
#include <errno.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <cassert>
|
||||
#include "fatal.h"
|
||||
|
||||
#include "Common.hpp"
|
||||
|
||||
PresetLoader::PresetLoader (int gx, int gy, std::string dirname = std::string()) :_dirname ( dirname ), _dir ( 0 )
|
||||
PresetLoader::PresetLoader (int gx, int gy, std::string dirname = std::string()) :_dirname ( dirname )
|
||||
{
|
||||
_presetFactoryManager.initialize(gx,gy);
|
||||
_presetFactoryManager.initialize(gx,gy);
|
||||
|
||||
std::vector<std::string> dirs{_dirname};
|
||||
std::vector<std::string> extensions = _presetFactoryManager.extensionsHandled();
|
||||
fileScanner = FileScanner(dirs, extensions);
|
||||
|
||||
// Do one scan
|
||||
if ( _dirname != std::string() )
|
||||
rescan();
|
||||
@ -45,106 +35,59 @@ PresetLoader::PresetLoader (int gx, int gy, std::string dirname = std::string())
|
||||
clear();
|
||||
}
|
||||
|
||||
PresetLoader::~PresetLoader()
|
||||
{
|
||||
if ( _dir )
|
||||
closedir ( _dir );
|
||||
}
|
||||
PresetLoader::~PresetLoader() {}
|
||||
|
||||
void PresetLoader::setScanDirectory ( std::string dirname )
|
||||
{
|
||||
_dirname = dirname;
|
||||
}
|
||||
|
||||
void PresetLoader::addScannedPresetFile(const std::string &path, const std::string &name) {
|
||||
auto ext = parseExtension(path);
|
||||
if (ext.empty())
|
||||
return;
|
||||
|
||||
ext = "." + ext;
|
||||
|
||||
// Verify extension is projectm or milkdrop
|
||||
if (!_presetFactoryManager.extensionHandled(ext))
|
||||
return;
|
||||
|
||||
// std::cout << "Loading preset file " << path << std::endl;
|
||||
|
||||
_entries.push_back(path);
|
||||
_presetNames.push_back(name + ext);
|
||||
}
|
||||
|
||||
void PresetLoader::rescan()
|
||||
{
|
||||
// std::cerr << "Rescanning..." << std::endl;
|
||||
|
||||
// Clear the directory entry collection
|
||||
clear();
|
||||
|
||||
// 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] == 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() );
|
||||
|
||||
// scan for presets
|
||||
using namespace std::placeholders;
|
||||
fileScanner.scan(std::bind(&PresetLoader::addScannedPresetFile, this, _1, _2));
|
||||
|
||||
// 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::unique_ptr<Preset> PresetLoader::loadPreset ( unsigned int index ) const
|
||||
std::unique_ptr<Preset> PresetLoader::loadPreset ( PresetIndex index ) const
|
||||
{
|
||||
|
||||
// Check that index isn't insane
|
||||
assert ( index < _entries.size() );
|
||||
return _presetFactoryManager.allocate
|
||||
( _entries[index], _presetNames[index] );
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<Preset> PresetLoader::loadPreset ( const std::string & url ) const
|
||||
{
|
||||
// std::cout << "Loading preset " << url << std::endl;
|
||||
|
||||
try {
|
||||
/// @bug probably should not use url for preset name
|
||||
return _presetFactoryManager.allocate
|
||||
@ -157,40 +100,7 @@ std::unique_ptr<Preset> PresetLoader::loadPreset ( const std::string & url ) co
|
||||
return std::unique_ptr<Preset>();
|
||||
}
|
||||
|
||||
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)
|
||||
void PresetLoader::setRating(PresetIndex index, int rating, const PresetRatingType ratingType)
|
||||
{
|
||||
const unsigned int ratingTypeIndex = static_cast<unsigned int>(ratingType);
|
||||
assert (index < _ratings[ratingTypeIndex].size());
|
||||
@ -199,11 +109,9 @@ void PresetLoader::setRating(unsigned int index, int rating, const PresetRatingT
|
||||
|
||||
_ratings[ratingTypeIndex][index] = rating;
|
||||
_ratingsSums[ratingType] += rating;
|
||||
|
||||
}
|
||||
|
||||
|
||||
unsigned int PresetLoader::addPresetURL ( const std::string & url, const std::string & presetName, const std::vector<int> & ratings)
|
||||
unsigned long PresetLoader::addPresetURL ( const std::string & url, const std::string & presetName, const std::vector<int> & ratings)
|
||||
{
|
||||
_entries.push_back(url);
|
||||
_presetNames.push_back ( presetName );
|
||||
@ -220,9 +128,8 @@ unsigned int PresetLoader::addPresetURL ( const std::string & url, const std::st
|
||||
return _entries.size()-1;
|
||||
}
|
||||
|
||||
void PresetLoader::removePreset ( unsigned int index )
|
||||
void PresetLoader::removePreset ( PresetIndex index )
|
||||
{
|
||||
|
||||
_entries.erase ( _entries.begin() + index );
|
||||
_presetNames.erase ( _presetNames.begin() + index );
|
||||
|
||||
@ -230,21 +137,19 @@ void PresetLoader::removePreset ( unsigned int index )
|
||||
_ratingsSums[i] -= _ratings[i][index];
|
||||
_ratings[i].erase ( _ratings[i].begin() + index );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
const std::string & PresetLoader::getPresetURL ( unsigned int index ) const
|
||||
const std::string & PresetLoader::getPresetURL ( PresetIndex index ) const
|
||||
{
|
||||
return _entries[index];
|
||||
}
|
||||
|
||||
const std::string & PresetLoader::getPresetName ( unsigned int index ) const
|
||||
const std::string & PresetLoader::getPresetName ( PresetIndex index ) const
|
||||
{
|
||||
return _presetNames[index];
|
||||
}
|
||||
|
||||
int PresetLoader::getPresetRating ( unsigned int index, const PresetRatingType ratingType ) const
|
||||
int PresetLoader::getPresetRating ( PresetIndex index, const PresetRatingType ratingType ) const
|
||||
{
|
||||
return _ratings[ratingType][index];
|
||||
}
|
||||
@ -258,23 +163,19 @@ const std::vector<int> & PresetLoader::getPresetRatingsSums() const {
|
||||
return _ratingsSums;
|
||||
}
|
||||
|
||||
void PresetLoader::setPresetName(unsigned int index, std::string name) {
|
||||
void PresetLoader::setPresetName(PresetIndex index, std::string name) {
|
||||
_presetNames[index] = name;
|
||||
}
|
||||
|
||||
void PresetLoader::insertPresetURL ( unsigned int index, const std::string & url, const std::string & presetName, const RatingList & ratings)
|
||||
void PresetLoader::insertPresetURL ( PresetIndex 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 (unsigned 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() );
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user