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:
Mischa Spiegelmock
2020-07-28 22:01:56 +03:00
committed by GitHub
parent e51b2c7d63
commit e49720ecfa
27 changed files with 379 additions and 330 deletions

View File

@ -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

View File

@ -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}
])

View File

@ -132,6 +132,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)../src\libprojectM\TimeKeeper.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)../src\libprojectM\timer.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)../src\libprojectM\wipemalloc.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)../src\libprojectM\FileScanner.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)../msvc\glew.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)../msvc\glew.c">
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CompileAsC</CompileAs>
@ -166,4 +167,4 @@
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -36,6 +36,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\libprojectM\MilkdropPresetFactory\PresetFrameIO.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\libprojectM\PresetFactory.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\libprojectM\ConfigFile.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\libprojectM\FileScanner.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\libprojectM\fftsg.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\libprojectM\KeyHandler.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\libprojectM\PCM.cpp" />

View File

@ -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;

View File

@ -0,0 +1,180 @@
//
// FileScanner.cpp
// libprojectM
//
//
#include "FileScanner.hpp"
FileScanner::FileScanner() {}
FileScanner::FileScanner(std::vector<std::string> &rootDirs, std::vector<std::string> &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
}

View File

@ -0,0 +1,60 @@
//
// FileScanner.hpp
// libprojectM
//
// Cross-platform directory traversal with filtering by extension
#ifndef FileScanner_hpp
#define FileScanner_hpp
#include <string>
#include <vector>
#include <iostream>
#include <functional>
#include "Common.hpp"
#include <string.h>
#ifdef WIN32
#include "dirent.h"
#else
#include <fts.h>
#endif
#ifdef __unix__
extern "C"
{
#include <errno.h>
#include <dirent.h>
}
#endif
#ifdef __APPLE__
extern "C"
{
#include <errno.h>
#include <dirent.h>
}
#endif
typedef std::function<void (std::string &path, std::string &name)> ScanCallback;
class FileScanner {
public:
FileScanner();
FileScanner(std::vector<std::string> &rootDirs, std::vector<std::string> &extensions);
void scan(ScanCallback cb);
std::string extensionMatches(std::string &filename);
private:
std::vector<std::string> _rootDirs;
std::vector<std::string> _extensions;
void scanGeneric(ScanCallback cb, const char *dir);
void scanPosix(ScanCallback cb);
void handleDirectoryError(std::string dir);
};
#endif /* FileScanner_hpp */

View File

@ -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 \

View File

@ -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" */

View File

@ -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<std::map<int, PerPixelEqn*>::iterator, bool> inserteeOption = per_pixel_eqn_tree.insert
(std::make_pair(per_pixel_eqn->index, per_pixel_eqn));

View File

@ -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;
}

View File

@ -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;

View File

@ -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<Preset> 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

View File

@ -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);

View File

@ -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;
};

View File

@ -29,7 +29,7 @@ public:
virtual std::unique_ptr<Preset> 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);

View File

@ -81,7 +81,7 @@ void PresetFactoryManager::registerFactory(const std::string & extensions, Prese
std::unique_ptr<Preset> 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<std::string> PresetFactoryManager::extensionsHandled() const {
std::vector<std::string> retval;
for (auto const& element : _factoryMap) {
retval.push_back(element.first);
}
return retval;
}

View File

@ -49,6 +49,8 @@ class PresetFactoryManager {
/// \returns true if a factory exists, false otherwise
bool extensionHandled(const std::string & extension) const;
std::unique_ptr<Preset> allocate(const std::string & url, const std::string & name);
std::vector<std::string> extensionsHandled() const;
private:
int _gx, _gy;

View File

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

View File

@ -5,34 +5,18 @@
#include <memory> // for auto pointers
#include <sys/types.h>
#ifdef WIN32
#include "dirent.h"
#endif
#ifdef __unix__
#include <dirent.h>
#endif
#ifdef EMSCRIPTEN
#include <dirent.h>
#endif
#ifdef __APPLE__
#include <dirent.h>
#endif
#include <vector>
#include <map>
#include "PresetFactoryManager.hpp"
#include "FileScanner.hpp"
class Preset;
class PresetFactory;
typedef std::size_t PresetIndex;
class PresetLoader {
public:
/// Initializes the preset loader with the target directory specified
PresetLoader(int gx, int gy, std::string dirname);
@ -40,21 +24,21 @@ class PresetLoader {
/// Load a preset by specifying its unique identifier given when the preset url
/// was added to this loader
std::unique_ptr<Preset> loadPreset(unsigned int index) const;
std::unique_ptr<Preset> loadPreset(PresetIndex index) const;
std::unique_ptr<Preset> loadPreset ( const std::string & url ) const;
/// Add a preset to the loader's collection.
/// \param url an url referencing the preset
/// \param presetName a name for the preset
/// \param rating an integer representing the goodness of the preset
/// \param ratings an list representing the goodness ratings
/// \returns The unique index assigned to the preset in the collection. Used with loadPreset
unsigned int addPresetURL ( const std::string & url, const std::string & presetName, const RatingList & ratings);
unsigned long addPresetURL(const std::string & url, const std::string & presetName, const RatingList & ratings);
/// Add a preset to the loader's collection.
/// \param index insertion index
/// \param url an url referencing the preset
/// \param presetName a name for the preset
/// \param rating an integer representing the goodness of the preset
void insertPresetURL (unsigned int index, const std::string & url, const std::string & presetName, const RatingList & ratings);
/// \param ratings an list representing the goodness ratings
void insertPresetURL (PresetIndex index, const std::string & url, const std::string & presetName, const RatingList & ratings);
/// Clears all presets from the collection
inline void clear() {
@ -72,19 +56,19 @@ class PresetLoader {
/// Removes a preset from the loader
/// \param index the unique identifier of the preset url to be removed
void removePreset(unsigned int index);
void removePreset(PresetIndex index);
/// Sets the rating of a preset to a new value
void setRating(unsigned int index, int rating, const PresetRatingType ratingType);
void setRating(PresetIndex index, int rating, const PresetRatingType ratingType);
/// Get a preset rating given an index
int getPresetRating ( unsigned int index, const PresetRatingType ratingType) const;
int getPresetRating ( PresetIndex index, const PresetRatingType ratingType) const;
/// Get a preset url given an index
const std::string & getPresetURL ( unsigned int index) const;
const std::string & getPresetURL ( PresetIndex index) const;
/// Get a preset name given an index
const std::string & getPresetName ( unsigned int index) const;
const std::string & getPresetName ( PresetIndex index) const;
/// Returns the number of presets in the active directory
inline std::size_t size() const {
@ -101,11 +85,12 @@ class PresetLoader {
/// Rescans the active preset directory
void rescan();
void setPresetName(unsigned int index, std::string name);
private:
void handleDirectoryError();
void setPresetName(PresetIndex index, std::string name);
protected:
void addScannedPresetFile(const std::string &path, const std::string &name);
std::string _dirname;
DIR * _dir;
std::vector<int> _ratingsSums;
mutable PresetFactoryManager _presetFactoryManager;
@ -115,8 +100,8 @@ class PresetLoader {
// Indexed by ratingType, preset position.
std::vector<RatingList> _ratings;
FileScanner fileScanner;
};
#endif

View File

@ -1,29 +1,13 @@
#include <algorithm>
#include <vector>
#include <memory>
#include "projectM-opengl.h"
#include "SOIL2/SOIL2.h"
#ifdef WIN32
#include "dirent.h"
#endif
#ifdef __unix__
#include <dirent.h>
#endif
#ifdef EMSCRIPTEN
#include <dirent.h>
#endif
#ifdef __APPLE__
#include <dirent.h>
#endif
#include "TextureManager.hpp"
#include "Common.hpp"
#include "IdleTextures.hpp"
#include "Texture.hpp"
/* OpenGL ES 2.0 cant handle converting textures fro GL_RGB to GL_RGBA via glTexImage2D
http://docs.gl/es2/glTexImage2D
@ -44,8 +28,8 @@ So because of this, we switch to a PerlinNoiseWithAlpha class to generate the no
TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX, const int texsizeY, std::string datadir):
presetsURL(_presetsURL)
{
presetsURL(_presetsURL) {
extensions.push_back(".jpg");
extensions.push_back(".dds");
extensions.push_back(".png");
@ -53,6 +37,13 @@ TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX
extensions.push_back(".bmp");
extensions.push_back(".dib");
std::vector<std::string> dirsToScan{datadir + "/presets", datadir + "/textures", _presetsURL};
FileScanner fileScanner = FileScanner(dirsToScan, extensions);
// scan for textures
using namespace std::placeholders;
fileScanner.scan(std::bind(&TextureManager::loadTexture, this, _1, _2));
Preload();
// if not data directory specified from user code
// we use the built-in default directory (unix prefix based)
@ -63,10 +54,6 @@ TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX
datadir = DATADIR_PATH;
#endif /** WIN32 */
loadTextureDir(datadir + "/presets");
loadTextureDir(datadir + "/textures");
loadTextureDir(_presetsURL);
// Create main texture ans associated samplers
mainTexture = new Texture("main", texsizeX, texsizeY, false);
mainTexture->getSampler(GL_REPEAT, GL_LINEAR);
@ -233,12 +220,12 @@ TextureSamplerDesc TextureManager::getTexture(const std::string fullName, const
// Remove extension
std::string lowerCaseFileName(fullName);
std::transform(lowerCaseFileName.begin(), lowerCaseFileName.end(), lowerCaseFileName.begin(), tolower);
for (size_t x = 0; x < extensions.size(); x++)
for (auto ext : extensions)
{
size_t found = lowerCaseFileName.find(extensions[x]);
size_t found = lowerCaseFileName.find(ext);
if (found != std::string::npos)
{
fileName.replace(int(found), extensions[x].size(), "");
fileName.replace(int(found), ext.size(), "");
break;
}
}
@ -272,25 +259,29 @@ TextureSamplerDesc TextureManager::tryLoadingTexture(const std::string name)
ExtractTextureSettings(name, wrap_mode, filter_mode, unqualifiedName);
for (size_t x = 0; x < extensions.size(); x++)
for (auto ext : extensions)
{
std::string filename = unqualifiedName + extensions[x];
std::string filename = unqualifiedName + ext;
std::string fullURL = presetsURL + PATH_SEPARATOR + filename;
texDesc = loadTexture(name, fullURL);
texDesc = loadTexture(fullURL, name);
if (texDesc.first != NULL)
{
std::cerr << "Located texture " << name << std::endl;
break;
}
}
std::cerr << "Failed to locate texture " << name << std::endl;
return texDesc;
}
TextureSamplerDesc TextureManager::loadTexture(const std::string name, const std::string fileName)
TextureSamplerDesc TextureManager::loadTexture(const std::string fileName, const std::string name)
{
int width, height;
// std::cout << "Loading texture " << name << " at " << fileName << std::endl;
unsigned int tex = SOIL_load_OGL_texture(
fileName.c_str(),
@ -313,64 +304,16 @@ TextureSamplerDesc TextureManager::loadTexture(const std::string name, const std
Sampler * sampler = newTexture->getSampler(wrap_mode, filter_mode);
if (textures.find(name) != textures.end()) {
// found duplicate.. this could be optimized
delete textures[name];
}
textures[name] = newTexture;
// std::cout << "Loaded texture " << name << std::endl;
return TextureSamplerDesc(newTexture, sampler);
}
void TextureManager::loadTextureDir(const std::string &dirname)
{
DIR * m_dir;
// Allocate a new a stream given the current directory name
if ((m_dir = opendir(dirname.c_str())) == NULL)
{
// std::cout<<"No Textures Loaded from "<<dirname<<std::endl;
return; // no files loaded. m_entries is empty
}
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 lowerCaseFileName(filename);
std::transform(lowerCaseFileName.begin(), lowerCaseFileName.end(), lowerCaseFileName.begin(), tolower);
// Remove extension
for (size_t x = 0; x < extensions.size(); x++)
{
size_t found = lowerCaseFileName.find(extensions[x]);
if (found != std::string::npos)
{
std::string name = filename;
name.replace(int(found), extensions[x].size(), "");
// Create full path name
std::string fullname = dirname + PATH_SEPARATOR + filename;
loadTexture(name, fullname);
break;
}
}
}
if (m_dir)
{
closedir(m_dir);
m_dir = 0;
}
}
TextureSamplerDesc TextureManager::getRandomTextureName(std::string random_id)
{
GLint wrap_mode;

View File

@ -7,6 +7,7 @@
#include <vector>
#include "projectM-opengl.h"
#include "Texture.hpp"
#include "FileScanner.hpp"
class TextureManager
@ -17,7 +18,6 @@ class TextureManager
Texture * mainTexture;
std::vector<std::string> random_textures;
void loadTextureDir(const std::string & dirname);
TextureSamplerDesc loadTexture(const std::string name, const std::string imageUrl);
void ExtractTextureSettings(const std::string qualifiedName, GLint &_wrap_mode, GLint &_filter_mode, std::string & name);
std::vector<std::string> extensions;

View File

@ -57,8 +57,8 @@ void Waveform::Draw(RenderContext &context)
std::transform(&value1[0], &value1[samples], &value1[0], bind2nd(std::multiplies<float>(), mult));
std::transform(&value2[0], &value2[samples], &value2[0], bind2nd(std::multiplies<float>(), mult));
#else
std::transform(&value1[0], &value1[samples], &value1[0], std::bind2nd(std::multiplies<float>(), mult));
std::transform(&value2[0], &value2[samples], &value2[0], std::bind2nd(std::multiplies<float>(), mult));
std::transform(&value1[0], &value1[samples], &value1[0], std::bind(std::multiplies<float>(), std::placeholders::_1, mult));
std::transform(&value2[0], &value2[samples], &value2[0], std::bind(std::multiplies<float>(), std::placeholders::_1, mult));
#endif /** WIN32 */
WaveformContext waveContext(samples, context.beatDetect);

View File

@ -128,6 +128,10 @@
1687174A20C33DF400947E7E /* Pipeline.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1687173520C33DF400947E7E /* Pipeline.hpp */; };
1687174B20C33DF400947E7E /* ShaderEngine.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1687173620C33DF400947E7E /* ShaderEngine.hpp */; };
1687174E20C33E1000947E7E /* RenderContext.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1687174D20C33E1000947E7E /* RenderContext.hpp */; };
169BC64724CC4D16007B7829 /* FileScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 169BC64524CC4D16007B7829 /* FileScanner.cpp */; };
169BC64824CC4D16007B7829 /* FileScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 169BC64524CC4D16007B7829 /* FileScanner.cpp */; };
169BC64924CC4D16007B7829 /* FileScanner.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 169BC64624CC4D16007B7829 /* FileScanner.hpp */; };
169BC64A24CC4D16007B7829 /* FileScanner.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 169BC64624CC4D16007B7829 /* FileScanner.hpp */; };
16A49E5E207A7CAE00E508EA /* ConfigFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 16178ABD207A68A500D3B0C8 /* ConfigFile.cpp */; };
16A49E62207A7CAE00E508EA /* fftsg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 16178AB5207A68A400D3B0C8 /* fftsg.cpp */; };
16A49E69207A7CAE00E508EA /* PCM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 16178AC1207A68A600D3B0C8 /* PCM.cpp */; };
@ -264,6 +268,8 @@
168C689320BB1FE0000AFC1B /* HLSLTree.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = HLSLTree.cpp; path = Renderer/hlslparser/src/HLSLTree.cpp; sourceTree = "<group>"; };
168C689420BB1FE0000AFC1B /* HLSLTokenizer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = HLSLTokenizer.cpp; path = Renderer/hlslparser/src/HLSLTokenizer.cpp; sourceTree = "<group>"; };
168C689520BB1FE0000AFC1B /* CodeWriter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CodeWriter.cpp; path = Renderer/hlslparser/src/CodeWriter.cpp; sourceTree = "<group>"; };
169BC64524CC4D16007B7829 /* FileScanner.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FileScanner.cpp; sourceTree = "<group>"; };
169BC64624CC4D16007B7829 /* FileScanner.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = FileScanner.hpp; sourceTree = "<group>"; };
16A49E57207A7C8C00E508EA /* libprojectM.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libprojectM.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
@ -417,6 +423,8 @@
16178AB8207A68A500D3B0C8 /* TimeKeeper.cpp */,
16178AB6207A68A400D3B0C8 /* timer.cpp */,
16178ABC207A68A500D3B0C8 /* wipemalloc.cpp */,
169BC64524CC4D16007B7829 /* FileScanner.cpp */,
169BC64624CC4D16007B7829 /* FileScanner.hpp */,
);
name = libProjectM;
sourceTree = "<group>";
@ -558,6 +566,7 @@
1687174E20C33E1000947E7E /* RenderContext.hpp in Headers */,
1687174B20C33DF400947E7E /* ShaderEngine.hpp in Headers */,
1687173C20C33DF400947E7E /* RenderItemMatcher.hpp in Headers */,
169BC64924CC4D16007B7829 /* FileScanner.hpp in Headers */,
1687174A20C33DF400947E7E /* Pipeline.hpp in Headers */,
1687174120C33DF400947E7E /* Renderer.hpp in Headers */,
1687173920C33DF400947E7E /* Renderable.hpp in Headers */,
@ -585,6 +594,7 @@
1612CA0F207A878900862A3A /* resource.h in Headers */,
1612CA00207A878900862A3A /* cocoatoprojectM.h in Headers */,
1612CA07207A878900862A3A /* wipemalloc.h in Headers */,
169BC64A24CC4D16007B7829 /* FileScanner.hpp in Headers */,
1612CA06207A878900862A3A /* sdltoprojectM.h in Headers */,
1612CA09207A878900862A3A /* fftsg.h in Headers */,
1612CA0E207A878900862A3A /* projectM-opengl.h in Headers */,
@ -756,6 +766,7 @@
166854482105E4FC0042793A /* Filters.hpp in Sources */,
1668544B2105E4FC0042793A /* PerlinNoise.hpp in Sources */,
1668544C2105E4FC0042793A /* PerPixelMesh.hpp in Sources */,
169BC64724CC4D16007B7829 /* FileScanner.cpp in Sources */,
1668544D2105E4FC0042793A /* Pipeline.hpp in Sources */,
1668544E2105E4FC0042793A /* PipelineContext.hpp in Sources */,
1668544F2105E4FC0042793A /* Renderable.hpp in Sources */,
@ -803,6 +814,7 @@
buildActionMask = 2147483647;
files = (
16A49E5E207A7CAE00E508EA /* ConfigFile.cpp in Sources */,
169BC64824CC4D16007B7829 /* FileScanner.cpp in Sources */,
16A49E62207A7CAE00E508EA /* fftsg.cpp in Sources */,
16A49E69207A7CAE00E508EA /* PCM.cpp in Sources */,
1612C9EC207A860000862A3A /* KeyHandler.cpp in Sources */,
@ -911,7 +923,7 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 1;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"GL_SILENCE_DEPRECATION=1",

View File

@ -463,14 +463,14 @@ template <class RandomAccessIterator>
void random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
const unsigned P)
{
return ::std::random_shuffle(first, last);
return random_shuffle(first, last);
}
template <class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
RandomNumberGenerator &rgen, const unsigned P)
{
return ::std::random_shuffle(first, last, rgen);
return random_shuffle(first, last, rgen);
}
template <class ForwardIterator, class T>

View File

@ -121,7 +121,7 @@
C37EBD3D19A0112900220265 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
C37EBD3F19A0112900220265 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
C37EBD4619A0112900220265 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
C37EBD5A19A0118600220265 /* iTunes Visualizer.pkg */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iTunes Visualizer.pkg"; sourceTree = "<group>"; };
C37EBD5A19A0118600220265 /* iTunes Visualizer.pkg */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.installer-pkg"; path = "iTunes Visualizer.pkg"; sourceTree = "<group>"; };
C37EBD5C19A0146F00220265 /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; name = images; path = ../images; sourceTree = "<group>"; };
C37EBD5E19A0164400220265 /* selectViz.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = selectViz.png; path = images/selectViz.png; sourceTree = "<group>"; };
C37EBD6019A01BEE00220265 /* projectM Visualizer.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "projectM Visualizer.entitlements"; sourceTree = "<group>"; };
@ -640,7 +640,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = NO;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
@ -697,7 +697,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = NO;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;

View File

@ -117,6 +117,7 @@
files = (
168F715921124C0E001806E7 /* config.inp in Support files */,
168F715A21124C14001806E7 /* fonts in Support files */,
169BC64224CC3FCA007B7829 /* presets in Support files */,
);
name = "Support files";
runOnlyForDeploymentPostprocessing = 0;
@ -294,7 +295,6 @@
168F714621120210001806E7 /* Frameworks */,
168F714721120210001806E7 /* Resources */,
168F7155211248DE001806E7 /* Executable */,
168F715721124BBB001806E7 /* Copy Presets */,
168F715821124BFC001806E7 /* Support files */,
168F715B21124CD1001806E7 /* Frameworks */,
168F715D21124CF8001806E7 /* Generate Installer Package */,
@ -418,22 +418,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
168F715721124BBB001806E7 /* Copy Presets */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"$(SRCROOT)/../../presets",
);
name = "Copy Presets";
outputPaths = (
"$(DERIVED_FILE_DIR)/presets",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/bash;
shellScript = "POUT=\"$BUILT_PRODUCTS_DIR\"/\"$CONTENTS_FOLDER_PATH/Resources/presets\"\nPIN=\"$SRCROOT\"/../../presets\n\nmkdir -p \"$POUT\"\nfor preset_dir in \"$PIN/\"*; do\n cp \"$preset_dir/\"* \"$POUT/\"\ndone\necho \"Copied presets to $POUT\"\n";
};
168F715D21124CF8001806E7 /* Generate Installer Package */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 12;