diff --git a/Makefile.am b/Makefile.am
index be8efb1ac..92cf4880e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,7 +11,6 @@ CLEANFILES=dist
# aka /usr/local/share/projectM
pm_data_dir = $(pkgdatadir)
pm_font_dir = $(pm_data_dir)/fonts
-pm_presets_dir = $(pm_data_dir)/presets
# files to install
pm_data__DATA = src/libprojectM/config.inp
@@ -19,13 +18,8 @@ pm_font__DATA = fonts/Vera.ttf fonts/VeraMono.ttf
# find and install all preset files
install-data-local:
-if ENABLE_PRESET_SUBDIRS
find "$(PRESETSDIR)" -type d -exec $(MKDIR_P) "$(DESTDIR)/$(pm_data_dir)/{}" \;
find "$(PRESETSDIR)" -type f -exec $(INSTALL_DATA) "{}" "$(DESTDIR)/$(pm_data_dir)/{}" \;
-else
- test -z $(DESTDIR)$(pkgdatadir) || $(MKDIR_P) $(DESTDIR)$(pm_presets_dir)
- find "$(PRESETSDIR)" -type f -print0 | LC_ALL=C sort -z | xargs -0 '-I{}' $(INSTALL_DATA) '{}' $(DESTDIR)$(pm_presets_dir)
-endif
# from https://stackoverflow.com/questions/30897170/ac-subst-does-not-expand-variable answer: https://stackoverflow.com/a/30960268
# ptomato https://stackoverflow.com/users/172999/ptomato
diff --git a/configure.ac b/configure.ac
index 341d26103..a83320508 100644
--- a/configure.ac
+++ b/configure.ac
@@ -32,7 +32,6 @@ AS_IF([test "x$enable_emscripten" = "xyes" || test "x$EMSCRIPTEN" = "xyes"], [
enable_threading=no
enable_gles=yes
enable_sdl=yes
- enable_preset_subdirs=no
], [
dnl Running in a normal OS (not emscripten)
AX_CHECK_GL
@@ -127,13 +126,6 @@ AC_ARG_ENABLE([gles],
AC_DEFINE([USE_GLES], [1], [Define USE_GLES])
])
-AC_ARG_ENABLE([preset_subdirs],
- AS_HELP_STRING([--enable-preset-subdirs], [Organize presets into subdirectories.]),
- [], [enable_preset_subdirs=no])
- AS_IF([test "x$enable_preset_subdirs" = "xyes"], [
- AC_DEFINE([ENABLE_PRESET_SUBDIRS], [1], [Define ENABLE_PRESET_SUBDIRS])
-])
-
dnl LLVM
dnl unfortuately AX_LLVM macro seems to be out of date, so we're going to rely on the user to make sure LLVM is installed correctly
AC_ARG_ENABLE([llvm],
@@ -228,7 +220,6 @@ AM_CONDITIONAL([ENABLE_QT], [test "x$enable_qt" = "xyes"])
AM_CONDITIONAL([ENABLE_JACK], [test "x$enable_jack" = "xyes"])
AM_CONDITIONAL([ENABLE_PULSEAUDIO], [test "x$enable_pulseaudio" = "xyes"])
AM_CONDITIONAL([ENABLE_EMSCRIPTEN], [test "x$enable_emscripten" = "xyes"])
-AM_CONDITIONAL([ENABLE_PRESET_SUBDIRS], [test "x$enable_preset_subdirs" = "xyes"])
my_CFLAGS="-Wall -Wchar-subscripts -Wformat-security -Wpointer-arith -Wshadow -Wsign-compare -Wtype-limits"
@@ -277,5 +268,4 @@ Jack: ${enable_jack}
OpenGLES: ${enable_gles}
Emscripten: ${enable_emscripten}
llvm: ${enable_llvm}
-Preset subdirs: ${enable_preset_subdirs}
])
diff --git a/msvc/projectM.vcxproj b/msvc/projectM.vcxproj
index 8f1f0588b..4066f1e17 100644
--- a/msvc/projectM.vcxproj
+++ b/msvc/projectM.vcxproj
@@ -132,6 +132,7 @@
+
CompileAsC
@@ -166,4 +167,4 @@
-
\ No newline at end of file
+
diff --git a/src/EyeTune/EyeTune.Shared/EyeTune.Shared.vcxitems b/src/EyeTune/EyeTune.Shared/EyeTune.Shared.vcxitems
index 30992d65f..760e7d02c 100644
--- a/src/EyeTune/EyeTune.Shared/EyeTune.Shared.vcxitems
+++ b/src/EyeTune/EyeTune.Shared/EyeTune.Shared.vcxitems
@@ -36,6 +36,7 @@
+
diff --git a/src/libprojectM/Common.hpp b/src/libprojectM/Common.hpp
index 45e248a1a..fdca3951c 100755
--- a/src/libprojectM/Common.hpp
+++ b/src/libprojectM/Common.hpp
@@ -213,7 +213,7 @@ inline std::string parseExtension(const std::string & filename) {
const std::size_t start = filename.find_last_of('.');
if (start == std::string::npos || start >= (filename.length()-1))
- return "";
+ return {};
std::string ext = filename.substr(start+1, filename.length());
std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
return ext;
diff --git a/src/libprojectM/FileScanner.cpp b/src/libprojectM/FileScanner.cpp
new file mode 100644
index 000000000..92459ccba
--- /dev/null
+++ b/src/libprojectM/FileScanner.cpp
@@ -0,0 +1,180 @@
+//
+// FileScanner.cpp
+// libprojectM
+//
+//
+
+#include "FileScanner.hpp"
+
+FileScanner::FileScanner() {}
+
+FileScanner::FileScanner(std::vector &rootDirs, std::vector &extensions) : _rootDirs(rootDirs), _extensions(extensions) {}
+
+void FileScanner::scan(ScanCallback cb) {
+#ifdef WIN32
+ for (auto dir : _rootDirs)
+ scanGeneric(cb, dir.c_str());
+#else
+ scanPosix(cb);
+#endif
+}
+
+void FileScanner::handleDirectoryError(std::string dir) {
+#ifdef WIN32
+ std::cerr << "[PresetLoader] warning: errno unsupported on win32 platforms. fix me" << std::endl;
+#else
+
+ std::cerr << dir << " scan error: ";
+
+ switch ( errno )
+ {
+ case ENOENT:
+ std::cerr << "ENOENT error. The path \"" << dir << "\" probably does not exist. \"man open\" for more info." << std::endl;
+ break;
+ case ENOMEM:
+ std::cerr << "out of memory!" << std::endl;
+ abort();
+ case ENOTDIR:
+ std::cerr << "directory specified is not a directory! Trying to continue..." << std::endl;
+ break;
+ case ENFILE:
+ std::cerr << "Your system has reached its open file limit. Trying to continue..." << std::endl;
+ break;
+ case EMFILE:
+ std::cerr << "too many files in use by projectM! Bailing!" << std::endl;
+ break;
+ case EACCES:
+ std::cerr << "permissions issue reading the specified preset directory." << std::endl;
+ break;
+ default:
+ break;
+ }
+#endif
+}
+
+std::string FileScanner::extensionMatches(std::string &filename) {
+ // returns file name without extension
+ // TODO: optimize me
+
+ std::string lowerCaseFileName(filename);
+ std::transform(lowerCaseFileName.begin(), lowerCaseFileName.end(), lowerCaseFileName.begin(), tolower);
+
+ // Remove extension
+ for (auto ext : _extensions)
+ {
+ size_t found = lowerCaseFileName.find(ext);
+ if (found != std::string::npos)
+ {
+ std::string name = filename;
+ name.replace(int(found), ext.size(), "");
+ return name;
+ }
+ }
+
+ return {};
+}
+
+
+// generic implementation using dirent
+void FileScanner::scanGeneric(ScanCallback cb, const char *currentDir) {
+ DIR * m_dir;
+
+ // Allocate a new a stream given the current directory name
+ if ((m_dir = opendir(currentDir)) == NULL)
+ {
+ return; // no files found in here
+ }
+
+ struct dirent * dir_entry;
+
+ while ((dir_entry = readdir(m_dir)) != NULL)
+ {
+ // Convert char * to friendly string
+ std::string filename(dir_entry->d_name);
+
+ if (filename.length() > 0 && filename[0] == '.')
+ continue;
+
+ std::string fullPath = std::string(currentDir) + PATH_SEPARATOR + filename;
+
+ if (dir_entry->d_type == DT_DIR) {
+ // recurse into dir
+ scanGeneric(cb, fullPath.c_str());
+ continue;
+ } else if (dir_entry->d_type != DT_REG && dir_entry->d_type != DT_LNK) {
+ // not regular file/link
+ continue;
+ }
+
+ auto nameMatched = extensionMatches(filename);
+ if (! nameMatched.empty())
+ cb(fullPath, nameMatched);
+ }
+
+ if (m_dir)
+ {
+ closedir(m_dir);
+ m_dir = 0;
+ }
+}
+
+#ifndef WIN32
+// more optimized posix "fts" directory traversal
+int fts_compare(const FTSENT** one, const FTSENT** two) {
+ return (strcmp((*one)->fts_name, (*two)->fts_name));
+}
+#endif
+
+void FileScanner::scanPosix(ScanCallback cb) {
+#ifndef WIN32
+
+ // efficient directory traversal
+ FTS* fileSystem = NULL;
+ FTSENT *node = NULL;
+
+ // list of directories to scan
+ auto rootDirCount = _rootDirs.size();
+ char **dirList = (char **)malloc(sizeof(char*) * (rootDirCount + 1));
+ for (unsigned long i = 0; i < rootDirCount; i++) {
+ dirList[i] = (char *) _rootDirs[i].c_str();
+ }
+ dirList[rootDirCount] = NULL;
+
+ // initialize file hierarchy traversal
+ fileSystem = fts_open(dirList, FTS_LOGICAL|FTS_NOCHDIR|FTS_NOSTAT, &fts_compare);
+ if (fileSystem == NULL) {
+ std::string s;
+ for (int i = 0; i < _rootDirs.size(); i++)
+ s += _rootDirs[i] + ' ';
+ handleDirectoryError(s);
+
+ free(dirList);
+ return;
+ }
+
+ std::string path, name, nameMatched;
+
+ // traverse dirList
+ while( (node = fts_read(fileSystem)) != NULL) {
+ switch (node->fts_info) {
+ case FTS_F:
+ case FTS_SL:
+ case FTS_NSOK:
+ // found a file
+ path = std::string(node->fts_path);
+ name = std::string(node->fts_name);
+
+ // check extension
+ nameMatched = extensionMatches(name);
+ if (! nameMatched.empty())
+ cb(path, nameMatched);
+ break;
+ default:
+ break;
+ }
+ }
+ fts_close(fileSystem);
+ free(dirList);
+
+#endif
+}
diff --git a/src/libprojectM/FileScanner.hpp b/src/libprojectM/FileScanner.hpp
new file mode 100644
index 000000000..6135ce751
--- /dev/null
+++ b/src/libprojectM/FileScanner.hpp
@@ -0,0 +1,60 @@
+//
+// FileScanner.hpp
+// libprojectM
+//
+// Cross-platform directory traversal with filtering by extension
+
+#ifndef FileScanner_hpp
+#define FileScanner_hpp
+
+#include
+#include
+#include
+#include
+#include "Common.hpp"
+#include
+
+#ifdef WIN32
+#include "dirent.h"
+#else
+#include
+#endif
+
+#ifdef __unix__
+extern "C"
+{
+#include
+#include
+}
+#endif
+
+#ifdef __APPLE__
+extern "C"
+{
+#include
+#include
+}
+#endif
+
+
+typedef std::function ScanCallback;
+
+class FileScanner {
+public:
+ FileScanner();
+ FileScanner(std::vector &rootDirs, std::vector &extensions);
+
+ void scan(ScanCallback cb);
+ std::string extensionMatches(std::string &filename);
+
+private:
+ std::vector _rootDirs;
+ std::vector _extensions;
+
+ void scanGeneric(ScanCallback cb, const char *dir);
+ void scanPosix(ScanCallback cb);
+ void handleDirectoryError(std::string dir);
+};
+
+
+#endif /* FileScanner_hpp */
diff --git a/src/libprojectM/Makefile.am b/src/libprojectM/Makefile.am
index a7799c8f0..5c084bc99 100644
--- a/src/libprojectM/Makefile.am
+++ b/src/libprojectM/Makefile.am
@@ -24,12 +24,12 @@ libprojectM_la_LIBADD = \
libprojectM_la_SOURCES = ConfigFile.cpp Preset.cpp PresetLoader.cpp timer.cpp \
KeyHandler.cpp PresetChooser.cpp TimeKeeper.cpp PCM.cpp PresetFactory.cpp \
fftsg.cpp wipemalloc.cpp PipelineMerger.cpp PresetFactoryManager.cpp projectM.cpp \
- TestRunner.cpp TestRunner.hpp \
+ TestRunner.cpp TestRunner.hpp FileScanner.cpp FileScanner.hpp\
Common.hpp PipelineMerger.hpp PresetLoader.hpp\
HungarianMethod.hpp Preset.hpp RandomNumberGenerators.hpp\
IdleTextures.hpp PresetChooser.hpp TimeKeeper.hpp\
KeyHandler.hpp PresetFactory.hpp projectM.hpp\
- BackgroundWorker.h \
+ BackgroundWorker.h \
PCM.hpp PresetFactoryManager.hpp\
projectM.hpp projectM-opengl.h \
ConfigFile.h \
diff --git a/src/libprojectM/MilkdropPresetFactory/InitCond.cpp b/src/libprojectM/MilkdropPresetFactory/InitCond.cpp
index 051433ffe..1c0b3a727 100755
--- a/src/libprojectM/MilkdropPresetFactory/InitCond.cpp
+++ b/src/libprojectM/MilkdropPresetFactory/InitCond.cpp
@@ -71,7 +71,7 @@ void InitCond::evaluate(bool evalUser)
/* WIP */
void InitCond::init_cond_to_string()
{
- int string_length;
+ unsigned long string_length;
char string[MAX_TOKEN_SIZE];
/* Create a string "param_name=val" */
diff --git a/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.cpp b/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.cpp
index 739183de5..e07636c7f 100755
--- a/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.cpp
+++ b/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.cpp
@@ -115,9 +115,7 @@ MilkdropPreset::~MilkdropPreset()
int MilkdropPreset::add_per_pixel_eqn(char * name, Expr * gen_expr)
{
-
PerPixelEqn * per_pixel_eqn = NULL;
- int index;
Param * param = NULL;
assert(gen_expr);
@@ -134,7 +132,7 @@ int MilkdropPreset::add_per_pixel_eqn(char * name, Expr * gen_expr)
return PROJECTM_FAILURE;
}
- index = per_pixel_eqn_tree.size();
+ auto index = per_pixel_eqn_tree.size();
/* Create the per pixel equation given the index, parameter, and general expression */
if ((per_pixel_eqn = new PerPixelEqn(index, param, gen_expr)) == NULL)
@@ -143,8 +141,6 @@ int MilkdropPreset::add_per_pixel_eqn(char * name, Expr * gen_expr)
return PROJECTM_FAILURE;
}
-
-
/* Insert the per pixel equation into the preset per pixel database */
std::pair::iterator, bool> inserteeOption = per_pixel_eqn_tree.insert
(std::make_pair(per_pixel_eqn->index, per_pixel_eqn));
diff --git a/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.hpp b/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.hpp
index c10fa43c3..c8fe7b795 100644
--- a/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.hpp
+++ b/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.hpp
@@ -61,16 +61,14 @@ public:
/// Load a MilkdropPreset by filename with input and output buffers specified.
/// \param absoluteFilePath the absolute file path of a MilkdropPreset to load from the file system
- /// \param MilkdropPresetName a descriptive name for the MilkdropPreset. Usually just the file name
- /// \param MilkdropPresetInputs a reference to read only projectM engine variables
- /// \param MilkdropPresetOutputs initialized and filled with data parsed from a MilkdropPreset
+ /// \param milkdropPresetName a descriptive name for the MilkdropPreset. Usually just the file name
+ /// \param presetOutputs initialized and filled with data parsed from a MilkdropPreset
MilkdropPreset(MilkdropPresetFactory *factory, const std::string & absoluteFilePath, const std::string & milkdropPresetName, PresetOutputs & presetOutputs);
/// Load a MilkdropPreset from an input stream with input and output buffers specified.
/// \param in an already initialized input stream to read the MilkdropPreset file from
- /// \param MilkdropPresetName a descriptive name for the MilkdropPreset. Usually just the file name
- /// \param MilkdropPresetInputs a reference to read only projectM engine variables
- /// \param MilkdropPresetOutputs initialized and filled with data parsed from a MilkdropPreset
+ /// \param milkdropPresetName a descriptive name for the MilkdropPreset. Usually just the file name
+ /// \param presetOutputs initialized and filled with data parsed from a MilkdropPreset
MilkdropPreset(MilkdropPresetFactory *factory, std::istream & in, const std::string & milkdropPresetName, PresetOutputs & presetOutputs);
~MilkdropPreset();
@@ -110,13 +108,11 @@ public:
/// \returns A MilkdropPreset output instance with values computed from most recent evaluateFrame()
PresetOutputs & presetOutputs() const
{
-
return _presetOutputs;
}
const PresetInputs & presetInputs() const
{
-
return _presetInputs;
}
diff --git a/src/libprojectM/MilkdropPresetFactory/MilkdropPresetFactory.cpp b/src/libprojectM/MilkdropPresetFactory/MilkdropPresetFactory.cpp
index ad966948e..863a61e43 100644
--- a/src/libprojectM/MilkdropPresetFactory/MilkdropPresetFactory.cpp
+++ b/src/libprojectM/MilkdropPresetFactory/MilkdropPresetFactory.cpp
@@ -188,8 +188,7 @@ PresetOutputs* MilkdropPresetFactory::createPresetOutputs(int gx, int gy)
presetOutputs->bSolarize = 0;
presetOutputs->bInvert = 0;
presetOutputs->bMotionVectorsOn = 1;
-
- presetOutputs->fWarpAnimSpeed = 0;
+ presetOutputs->fWarpAnimSpeed = 0;
presetOutputs->fWarpScale = 0;
presetOutputs->fShader = 0;
diff --git a/src/libprojectM/MilkdropPresetFactory/MilkdropPresetFactory.hpp b/src/libprojectM/MilkdropPresetFactory/MilkdropPresetFactory.hpp
index 76802b170..b63adec9e 100644
--- a/src/libprojectM/MilkdropPresetFactory/MilkdropPresetFactory.hpp
+++ b/src/libprojectM/MilkdropPresetFactory/MilkdropPresetFactory.hpp
@@ -21,18 +21,16 @@ class DLLEXPORT PresetInputs;
class MilkdropPresetFactory : public PresetFactory {
public:
-
MilkdropPresetFactory(int gx, int gy);
virtual ~MilkdropPresetFactory();
+ // called by ~MilkdropPreset
+ void releasePreset(Preset *preset);
std::unique_ptr allocate(const std::string & url, const std::string & name = std::string(),
const std::string & author = std::string());
- std::string supportedExtensions() const { return "milk prjm"; }
-
- // called by ~MilkdropPreset
- void releasePreset(Preset *preset);
+ std::string supportedExtensions() const { return ".milk .prjm"; }
private:
static PresetOutputs* createPresetOutputs(int gx, int gy);
@@ -40,7 +38,6 @@ private:
int gx;
int gy;
PresetOutputs * _presetOutputsCache;
- //PresetInputs _presetInputs;
};
#endif
diff --git a/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.cpp b/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.cpp
index 47d44cf27..bb409371b 100755
--- a/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.cpp
+++ b/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.cpp
@@ -42,7 +42,7 @@ void PerPixelEqn::evaluate(int mesh_i, int mesh_j)
assign_expr->eval( mesh_i, mesh_j );
}
-PerPixelEqn::PerPixelEqn(int _index, Param * param, Expr * gen_expr):index(_index)
+PerPixelEqn::PerPixelEqn(unsigned long _index, Param * param, Expr * gen_expr):index(_index)
{
assert(index >= 0);
assert(param != 0);
diff --git a/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.hpp b/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.hpp
index 06e72dadc..3db2015cf 100755
--- a/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.hpp
+++ b/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.hpp
@@ -56,7 +56,7 @@ public:
void evaluate(int mesh_i, int mesh_j);
virtual ~PerPixelEqn();
- PerPixelEqn(int index, Param * param, Expr * gen_expr);
+ PerPixelEqn(unsigned long index, Param * param, Expr * gen_expr);
Expr *assign_expr;
};
diff --git a/src/libprojectM/NativePresetFactory/NativePresetFactory.hpp b/src/libprojectM/NativePresetFactory/NativePresetFactory.hpp
index 591f9bec0..daba75bb0 100644
--- a/src/libprojectM/NativePresetFactory/NativePresetFactory.hpp
+++ b/src/libprojectM/NativePresetFactory/NativePresetFactory.hpp
@@ -29,7 +29,7 @@ public:
virtual std::unique_ptr allocate(const std::string & url, const std::string & name = std::string(),
const std::string & author = std::string());
- virtual std::string supportedExtensions() const { return "so dylib"; }
+ virtual std::string supportedExtensions() const { return ".so .dylib"; }
private:
PresetLibrary * loadLibrary(const std::string & url);
diff --git a/src/libprojectM/PresetFactoryManager.cpp b/src/libprojectM/PresetFactoryManager.cpp
index c8baa2967..aac38ccbd 100644
--- a/src/libprojectM/PresetFactoryManager.cpp
+++ b/src/libprojectM/PresetFactoryManager.cpp
@@ -81,7 +81,7 @@ void PresetFactoryManager::registerFactory(const std::string & extensions, Prese
std::unique_ptr PresetFactoryManager::allocate(const std::string & url, const std::string & name)
{
try {
- const std::string extension = parseExtension (url);
+ const std::string extension = "." + parseExtension(url);
return factory(extension).allocate(url, name);
} catch (const PresetFactoryException & e) {
@@ -98,7 +98,7 @@ PresetFactory & PresetFactoryManager::factory(const std::string & extension) {
if (!extensionHandled(extension)) {
std::ostringstream os;
- os << "No preset factory associated with \"" << extension << "\"." << std::endl;
+ os << "No preset factory associated with \"" << extension << "\"." << std::endl;
throw PresetFactoryException(os.str());
}
return *_factoryMap[extension];
@@ -107,3 +107,11 @@ PresetFactory & PresetFactoryManager::factory(const std::string & extension) {
bool PresetFactoryManager::extensionHandled(const std::string & extension) const {
return _factoryMap.count(extension);
}
+
+std::vector PresetFactoryManager::extensionsHandled() const {
+ std::vector retval;
+ for (auto const& element : _factoryMap) {
+ retval.push_back(element.first);
+ }
+ return retval;
+}
diff --git a/src/libprojectM/PresetFactoryManager.hpp b/src/libprojectM/PresetFactoryManager.hpp
index 7a9867acb..05f9e716f 100644
--- a/src/libprojectM/PresetFactoryManager.hpp
+++ b/src/libprojectM/PresetFactoryManager.hpp
@@ -49,6 +49,8 @@ class PresetFactoryManager {
/// \returns true if a factory exists, false otherwise
bool extensionHandled(const std::string & extension) const;
std::unique_ptr allocate(const std::string & url, const std::string & name);
+ std::vector extensionsHandled() const;
+
private:
int _gx, _gy;
diff --git a/src/libprojectM/PresetLoader.cpp b/src/libprojectM/PresetLoader.cpp
index a685d22cb..2b4ef100f 100644
--- a/src/libprojectM/PresetLoader.cpp
+++ b/src/libprojectM/PresetLoader.cpp
@@ -15,29 +15,19 @@
#include
#include
#include
-
-#ifdef __unix__
-extern "C"
-{
-#include
-}
-#endif
-
-#ifdef __APPLE__
-extern "C"
-{
-#include
-}
-#endif
-
+#include
#include
#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 dirs{_dirname};
+ std::vector 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 alphaSortedFileSet;
- std::set 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::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() );
-
+ // 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(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
+std::unique_ptr 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 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 PresetLoader::loadPreset ( const std::string & url ) co
return std::unique_ptr();
}
-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(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 & ratings)
+unsigned long PresetLoader::addPresetURL ( const std::string & url, const std::string & presetName, const std::vector & 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 & 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() );
-
-
}
diff --git a/src/libprojectM/PresetLoader.hpp b/src/libprojectM/PresetLoader.hpp
index b6ca27829..df314387c 100644
--- a/src/libprojectM/PresetLoader.hpp
+++ b/src/libprojectM/PresetLoader.hpp
@@ -5,34 +5,18 @@
#include // for auto pointers
#include
-#ifdef WIN32
-#include "dirent.h"
-#endif
-
-#ifdef __unix__
-#include
-#endif
-
-#ifdef EMSCRIPTEN
-#include
-#endif
-
-#ifdef __APPLE__
-#include
-#endif
-
#include
#include