| /** |
| * projectM -- Milkdrop-esque visualisation SDK |
| * Copyright (C)2003-2004 projectM Team |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| * See 'LICENSE.txt' included within this release |
| * |
| */ |
| #include "RenderItemMatcher.hpp" |
| #include "RenderItemMergeFunction.hpp" |
| #include "fatal.h" |
| #include "Common.hpp" |
| |
| #ifdef WIN32 |
| #include "win32-dirent.h" |
| #endif |
| |
| #include "timer.h" |
| #include <iostream> |
| #ifdef LINUX |
| #include "time.h" |
| #endif |
| |
| #ifdef WIN32 |
| #include <time.h> |
| #endif |
| #include "PipelineContext.hpp" |
| #include <iostream> |
| #include "projectM.hpp" |
| #include "BeatDetect.hpp" |
| #include "Preset.hpp" |
| #include "PipelineMerger.hpp" |
| #include "PCM.hpp" //Sound data handler (buffering, FFT, etc.) |
| |
| #include <map> |
| |
| #include "Renderer.hpp" |
| #include "PresetChooser.hpp" |
| #include "ConfigFile.h" |
| #include "TextureManager.hpp" |
| #include "TimeKeeper.hpp" |
| #include "RenderItemMergeFunction.hpp" |
| |
| #ifdef USE_THREADS |
| #include "pthread.h" |
| |
| pthread_mutex_t mutex; |
| pthread_cond_t condition; |
| pthread_t thread; |
| |
| #ifdef SYNC_PRESET_SWITCHES |
| pthread_mutex_t preset_mutex; |
| #endif |
| #endif |
| |
| |
| projectM::~projectM() |
| { |
| #ifdef USE_THREADS |
| std::cout << "[projectM] thread "; |
| printf ("c"); |
| running = false; |
| printf ("l"); |
| pthread_cond_signal (&condition); |
| printf ("e"); |
| pthread_mutex_unlock (&mutex); |
| printf ("a"); |
| pthread_detach (thread); |
| printf ("n"); |
| pthread_cond_destroy (&condition); |
| printf ("u"); |
| pthread_mutex_destroy (&mutex); |
| #ifdef SYNC_PRESET_SWITCHES |
| pthread_mutex_destroy (&preset_mutex); |
| #endif |
| |
| printf ("p"); |
| std::cout << std::endl; |
| #endif |
| destroyPresetTools(); |
| |
| if (renderer) |
| delete (renderer); |
| if (beatDetect) |
| delete (beatDetect); |
| if (_pcm) { |
| delete (_pcm); |
| _pcm = 0; |
| } |
| |
| delete (_pipelineContext); |
| delete (_pipelineContext2); |
| } |
| |
| unsigned |
| projectM::initRenderToTexture() |
| { |
| return renderer->initRenderToTexture(); |
| } |
| |
| void |
| projectM::projectM_resetTextures() |
| { |
| renderer->ResetTextures(); |
| } |
| |
| |
| projectM::projectM (std::string config_file, int flags) |
| : beatDetect (0), |
| renderer (0), |
| _pcm (0), |
| m_presetPos (0), |
| m_flags (flags), |
| _pipelineContext (new PipelineContext()), |
| _pipelineContext2 (new PipelineContext()) |
| { |
| readConfig (config_file); |
| projectM_reset(); |
| projectM_resetGL (_settings.windowWidth, _settings.windowHeight); |
| } |
| |
| projectM::projectM (Settings settings, int flags) |
| : beatDetect (0), |
| renderer (0), |
| _pcm (0), |
| m_presetPos (0), |
| m_flags (flags), |
| _pipelineContext (new PipelineContext()), |
| _pipelineContext2 (new PipelineContext()) |
| { |
| readSettings (settings); |
| projectM_reset(); |
| projectM_resetGL (_settings.windowWidth, _settings.windowHeight); |
| } |
| |
| |
| bool |
| projectM::writeConfig ( |
| const std::string & configFile, |
| const Settings & settings) |
| { |
| |
| ConfigFile config (configFile); |
| |
| config.add ("Mesh X", settings.meshX); |
| config.add ("Mesh Y", settings.meshY); |
| config.add ("Texture Size", settings.textureSize); |
| config.add ("FPS", settings.fps); |
| config.add ("Window Width", settings.windowWidth); |
| config.add ("Window Height", settings.windowHeight); |
| config.add ("Smooth Preset Duration", settings.smoothPresetDuration); |
| config.add ("Preset Duration", settings.presetDuration); |
| config.add ("Preset Path", settings.presetURL); |
| config.add ("Title Font", settings.titleFontURL); |
| config.add ("Menu Font", settings.menuFontURL); |
| config.add ("Hard Cut Sensitivity", settings.beatSensitivity); |
| config.add ("Aspect Correction", settings.aspectCorrection); |
| config.add ("Easter Egg Parameter", settings.easterEgg); |
| config.add ("Shuffle Enabled", settings.shuffleEnabled); |
| config.add ("Soft Cut Ratings Enabled", settings.softCutRatingsEnabled); |
| std::fstream file (configFile.c_str()); |
| |
| if (file) { |
| file << config; |
| return true; |
| } else |
| return false; |
| } |
| |
| |
| |
| void |
| projectM::readConfig (const std::string & configFile) |
| { |
| std::cout << "[projectM] config file: " << configFile << std::endl; |
| |
| ConfigFile config (configFile); |
| _settings.meshX = config.read<int> ("Mesh X", 32); |
| _settings.meshY = config.read<int> ("Mesh Y", 24); |
| _settings.textureSize = config.read<int> ("Texture Size", 512); |
| _settings.fps = config.read<int> ("FPS", 35); |
| _settings.windowWidth = config.read<int> ("Window Width", 512); |
| _settings.windowHeight = config.read<int> ("Window Height", 512); |
| _settings.smoothPresetDuration = |
| config.read<int> ("Smooth Preset Duration", |
| config.read<int> ("Smooth Transition Duration", 10)); |
| _settings.presetDuration = config.read<int> ("Preset Duration", 15); |
| |
| #ifdef LINUX |
| _settings.presetURL = config.read<string> ("Preset Path", CMAKE_INSTALL_PREFIX "/share/projectM/presets"); |
| #endif |
| |
| #ifdef __APPLE__ |
| /// @bug awful hardcoded hack- need to add intelligence to cmake wrt bundling - carm |
| _settings.presetURL = config.read<string> ("Preset Path", "../Resources/presets"); |
| #endif |
| |
| #ifdef WIN32 |
| _settings.presetURL = config.read<string> ("Preset Path", CMAKE_INSTALL_PREFIX "/share/projectM/presets"); |
| #endif |
| |
| #ifdef __APPLE__ |
| _settings.titleFontURL = config.read<string> |
| ("Title Font", "../Resources/fonts/Vera.tff"); |
| _settings.menuFontURL = config.read<string> |
| ("Menu Font", "../Resources/fonts/VeraMono.ttf"); |
| #endif |
| |
| #ifdef LINUX |
| _settings.titleFontURL = config.read<string> |
| ("Title Font", projectM_FONT_TITLE); |
| _settings.menuFontURL = config.read<string> |
| ("Menu Font", projectM_FONT_MENU); |
| #endif |
| |
| #ifdef WIN32 |
| _settings.titleFontURL = config.read<string> |
| ("Title Font", projectM_FONT_TITLE); |
| _settings.menuFontURL = config.read<string> |
| ("Menu Font", projectM_FONT_MENU); |
| #endif |
| |
| |
| _settings.shuffleEnabled = config.read<bool> ("Shuffle Enabled", true); |
| _settings.easterEgg = config.read<float> ("Easter Egg Parameter", 0.0); |
| _settings.softCutRatingsEnabled = config.read<float> ("Soft Cut Ratings Enabled", false); |
| |
| projectM_init (_settings.meshX, _settings.meshY, |
| _settings.fps, |
| _settings.textureSize, |
| _settings.windowWidth, _settings.windowHeight); |
| |
| _settings.beatSensitivity = |
| beatDetect->beat_sensitivity = config.read<float> ("Hard Cut Sensitivity", 10.0); |
| |
| |
| if (config.read ("Aspect Correction", true)) |
| { |
| _settings.aspectCorrection = true; |
| renderer->correction = true; |
| } |
| else |
| { |
| _settings.aspectCorrection = false; |
| renderer->correction = false; |
| } |
| } |
| |
| |
| void |
| projectM::readSettings (const Settings & settings) |
| { |
| _settings.meshX = settings.meshX; |
| _settings.meshY = settings.meshY; |
| _settings.textureSize = settings.textureSize; |
| _settings.fps = settings.fps; |
| _settings.windowWidth = settings.windowWidth; |
| _settings.windowHeight = settings.windowHeight; |
| _settings.smoothPresetDuration = settings.smoothPresetDuration; |
| _settings.presetDuration = settings.presetDuration; |
| _settings.softCutRatingsEnabled = settings.softCutRatingsEnabled; |
| |
| _settings.presetURL = settings.presetURL; |
| _settings.titleFontURL = settings.titleFontURL; |
| _settings.menuFontURL = settings.menuFontURL; |
| _settings.shuffleEnabled = settings.shuffleEnabled; |
| |
| _settings.easterEgg = settings.easterEgg; |
| |
| projectM_init (_settings.meshX, _settings.meshY, |
| _settings.fps, |
| _settings.textureSize, |
| _settings.windowWidth, _settings.windowHeight); |
| |
| _settings.beatSensitivity = settings.beatSensitivity; |
| _settings.aspectCorrection = settings.aspectCorrection; |
| } |
| |
| #ifdef USE_THREADS |
| static void |
| *thread_callback (void *prjm) |
| { |
| projectM *p = (projectM *)prjm; |
| |
| p->thread_func (prjm); |
| return NULL; |
| } |
| |
| |
| void * |
| projectM::thread_func (void *vptr_args) |
| { |
| pthread_mutex_lock (&mutex); |
| // printf ("in thread: %f\n", timeKeeper->PresetProgressB()); |
| while (true) |
| { |
| pthread_cond_wait (&condition, &mutex); |
| if (!running) |
| { |
| pthread_mutex_unlock (&mutex); |
| return NULL; |
| } |
| evaluateSecondPreset(); |
| } |
| } |
| #endif /* USE_THREADS */ |
| |
| void |
| projectM::evaluateSecondPreset() |
| { |
| pipelineContext2().time = timeKeeper->GetRunningTime(); |
| pipelineContext2().frame = timeKeeper->PresetFrameB(); |
| pipelineContext2().progress = timeKeeper->PresetProgressB(); |
| |
| m_activePreset2->Render (*beatDetect, pipelineContext2()); |
| } |
| |
| void |
| projectM::renderFrame() |
| { |
| #ifdef SYNC_PRESET_SWITCHES |
| pthread_mutex_lock (&preset_mutex); |
| #endif |
| |
| #ifdef DEBUG |
| char fname[1024]; |
| FILE *f = NULL; |
| int index = 0; |
| int x, y; |
| #endif |
| |
| timeKeeper->UpdateTimers(); |
| /* |
| if (timeKeeper->IsSmoothing()) |
| { |
| printf ("Smoothing A:%f, B:%f, S:%f\n", |
| timeKeeper->PresetProgressA(), |
| timeKeeper->PresetProgressB(), |
| timeKeeper->SmoothRatio()); |
| } |
| else |
| { |
| printf (" A:%f\n", timeKeeper->PresetProgressA()); |
| }*/ |
| |
| mspf = (int) (1000.0 / (float) settings().fps); //milliseconds per frame |
| |
| /// @bug who is responsible for updating this now?" |
| pipelineContext().time = timeKeeper->GetRunningTime(); |
| pipelineContext().frame = timeKeeper->PresetFrameA(); |
| pipelineContext().progress = timeKeeper->PresetProgressA(); |
| |
| //m_activePreset->Render (*beatDetect, pipelineContext()); |
| |
| beatDetect->detectFromSamples(); |
| |
| //m_activePreset->evaluateFrame(); |
| |
| //if the preset isn't locked and there are more presets |
| if (renderer->noSwitch == false && !m_presetChooser->empty()) |
| { |
| //if preset is done and we're not already switching |
| if (timeKeeper->PresetProgressA() >= 1.0 && !timeKeeper->IsSmoothing()) |
| { |
| if (settings().shuffleEnabled) |
| selectRandom (false); |
| else |
| selectNext (false); |
| } |
| else if ( beatDetect->vol-beatDetect->vol_old>beatDetect->beat_sensitivity |
| && timeKeeper->CanHardCut()) |
| { |
| // printf ("Hard Cut\n"); |
| if (settings().shuffleEnabled) |
| selectRandom (true); |
| else |
| selectNext (true); |
| } |
| } |
| |
| |
| if ( timeKeeper->IsSmoothing() |
| && timeKeeper->SmoothRatio() <= 1.0 |
| && !m_presetChooser->empty()) |
| { |
| // printf ("start thread\n"); |
| assert (m_activePreset2.get()); |
| |
| #ifdef USE_THREADS |
| pthread_cond_signal (&condition); |
| pthread_mutex_unlock (&mutex); |
| #endif |
| m_activePreset->Render (*beatDetect, pipelineContext()); |
| |
| #ifdef USE_THREADS |
| pthread_mutex_lock (&mutex); |
| #else |
| evaluateSecondPreset(); |
| #endif |
| |
| Pipeline pipeline; |
| |
| pipeline.setStaticPerPixel (settings().meshX, settings().meshY); |
| |
| assert (_matcher); |
| PipelineMerger::mergePipelines (m_activePreset->pipeline(), |
| m_activePreset2->pipeline(), |
| pipeline, |
| _matcher->matchResults(), |
| *_merger, |
| timeKeeper->SmoothRatio()); |
| |
| renderer->RenderFrame (pipeline, pipelineContext()); |
| |
| pipeline.drawables.clear(); |
| |
| /* |
| while (!pipeline.drawables.empty()) { |
| delete (pipeline.drawables.back()); |
| pipeline.drawables.pop_back(); |
| } */ |
| } |
| else |
| { |
| if (timeKeeper->IsSmoothing() && timeKeeper->SmoothRatio() > 1.0) |
| { |
| //printf ("End Smooth\n"); |
| m_activePreset = m_activePreset2; |
| timeKeeper->EndSmoothing(); |
| } |
| //printf ("Normal\n"); |
| |
| m_activePreset->Render (*beatDetect, pipelineContext()); |
| renderer->RenderFrame (m_activePreset->pipeline(), pipelineContext()); |
| } |
| |
| // std::cout<< m_activePreset->absoluteFilePath()<<std::endl; |
| // renderer->presetName = m_activePreset->absoluteFilePath(); |
| |
| count++; |
| |
| #ifndef WIN32 |
| /** Frame-rate limiter */ |
| /** Compute once per preset */ |
| if (this->count % 100 == 0) |
| { |
| this->renderer->realfps = 100.0 |
| / ((getTicks (&timeKeeper->startTime) |
| - this->fpsstart) / 1000); |
| this->fpsstart = getTicks (&timeKeeper->startTime); |
| } |
| |
| int timediff = getTicks (&timeKeeper->startTime) - this->timestart; |
| |
| if (timediff < this->mspf) |
| { |
| // printf ("%s:",this->mspf-timediff); |
| int sleepTime = (unsigned int) (this->mspf - timediff) * 1000; |
| // DWRITE ("usleep: %d\n", sleepTime); |
| if (sleepTime > 0 && sleepTime < 100000) |
| { |
| if (usleep (sleepTime) != 0) {} |
| } |
| } |
| this->timestart = getTicks (&timeKeeper->startTime); |
| #endif /** !WIN32 */ |
| |
| #ifdef SYNC_PRESET_SWITCHES |
| pthread_mutex_unlock (&preset_mutex); |
| #endif |
| } |
| |
| void |
| projectM::projectM_reset() |
| { |
| this->mspf = 0; |
| this->timed = 0; |
| this->timestart = 0; |
| this->count = 0; |
| |
| this->fpsstart = 0; |
| |
| setlocale (LC_NUMERIC, "C"); |
| |
| projectM_resetengine(); |
| } |
| |
| void |
| projectM::projectM_init ( |
| int gx, |
| int gy, |
| int fps, |
| int texsize, |
| int width, |
| int height |
| ) |
| { |
| setlocale (LC_NUMERIC, "C"); |
| |
| /** Initialise start time */ |
| timeKeeper = new TimeKeeper (_settings.presetDuration, |
| _settings.smoothPresetDuration, |
| _settings.easterEgg); |
| |
| /** Nullify frame stash */ |
| |
| /** Initialise per-pixel matrix calculations */ |
| /** We need to initialise this before the builtin param db otherwise bass/mid etc won't bind correctly */ |
| assert (!beatDetect); |
| |
| if (!_pcm) |
| _pcm = new PCM(); |
| assert (pcm()); |
| beatDetect = new BeatDetect (_pcm); |
| |
| if (_settings.fps > 0) |
| mspf = (int) (1000.0 / (float) _settings.fps); |
| else |
| mspf = 0; |
| |
| this->renderer = new Renderer (width, height, |
| gx, gy, |
| texsize, |
| beatDetect, |
| settings().presetURL, |
| settings().titleFontURL, |
| settings().menuFontURL); |
| |
| running = true; |
| |
| initPresetTools (gx, gy); |
| |
| |
| #ifdef USE_THREADS |
| pthread_mutex_init (&mutex, NULL); |
| |
| #ifdef SYNC_PRESET_SWITCHES |
| pthread_mutex_init (&preset_mutex, NULL); |
| #endif |
| |
| pthread_cond_init (&condition, NULL); |
| if (pthread_create (&thread, NULL, thread_callback, this) != 0) |
| { |
| |
| std::cerr << "[projectM] failed to allocate a thread! try building with option USE_THREADS turned off" << std::endl;; |
| exit (EXIT_FAILURE); |
| } |
| pthread_mutex_lock (&mutex); |
| #endif /* USE_THREADS */ |
| |
| /// @bug order of operatoins here is busted |
| //renderer->setPresetName (m_activePreset->name()); |
| timeKeeper->StartPreset(); |
| assert (pcm()); |
| |
| pipelineContext().fps = fps; |
| pipelineContext2().fps = fps; |
| } |
| |
| /* Reinitializes the engine variables to a default (conservative and sane) value */ |
| void |
| projectM::projectM_resetengine() |
| { |
| if (beatDetect != NULL) |
| { |
| beatDetect->reset(); |
| } |
| } |
| |
| /** Resets OpenGL state */ |
| void |
| projectM::projectM_resetGL (int w, int h) |
| { |
| /** Stash the new dimensions */ |
| renderer->reset (w,h); |
| } |
| |
| /** Sets the title to display */ |
| void |
| projectM::projectM_setTitle (std::string title) |
| { |
| if (title != renderer->title) |
| { |
| renderer->title=title; |
| renderer->drawtitle=1; |
| } |
| } |
| |
| |
| int projectM::initPresetTools (int gx, int gy) |
| { |
| /* Set the seed to the current time in seconds */ |
| srand (time (NULL)); |
| |
| std::string url = (m_flags & FLAG_DISABLE_PLAYLIST_LOAD) |
| ? std::string() |
| : settings().presetURL; |
| |
| if ((m_presetLoader = new PresetLoader (gx, gy, url)) == 0) |
| { |
| m_presetLoader = 0; |
| std::cerr << "[projectM] error allocating preset loader" << std::endl; |
| return PROJECTM_FAILURE; |
| } |
| |
| if ((m_presetChooser = new PresetChooser (*m_presetLoader, settings().softCutRatingsEnabled)) == 0) |
| { |
| delete (m_presetLoader); |
| |
| m_presetChooser = 0; |
| m_presetLoader = 0; |
| |
| std::cerr << "[projectM] error allocating preset chooser" << std::endl; |
| return PROJECTM_FAILURE; |
| } |
| |
| // Start the iterator |
| if (!m_presetPos) |
| m_presetPos = new PresetIterator(); |
| |
| // Initialize a preset queue position as well |
| // m_presetQueuePos = new PresetIterator(); |
| |
| // Start at end ptr- this allows next/previous to easily be done from this position. |
| *m_presetPos = m_presetChooser->end(); |
| |
| // Load idle preset |
| std::cerr << "[projectM] Allocating idle preset..." << std::endl; |
| m_activePreset = m_presetLoader->loadPreset |
| ("idle://Geiss & Sperl - Feedback (projectM idle HDR mix).milk"); |
| |
| renderer->SetPipeline (m_activePreset->pipeline()); |
| |
| // Case where no valid presets exist in directory. Could also mean |
| // playlist initialization was deferred |
| if (m_presetChooser->empty()) |
| { |
| //std::cerr << "[projectM] warning: no valid files found in preset directory \"" |
| //<< m_presetLoader->directoryName() << "\"" << std::endl; |
| } |
| |
| _matcher = new RenderItemMatcher(); |
| _merger = new MasterRenderItemMerge(); |
| //_merger->add (new WaveFormMergeFunction()); |
| _merger->add (new ShapeMerge()); |
| _merger->add (new BorderMerge()); |
| //_merger->add (new BorderMergeFunction()); |
| |
| /// @bug These should be requested by the preset factories. |
| _matcher->distanceFunction().addMetric (new ShapeXYDistance()); |
| |
| //std::cerr << "[projectM] Idle preset allocated." << std::endl; |
| |
| projectM_resetengine(); |
| |
| //std::cerr << "[projectM] engine has been reset." << std::endl; |
| return PROJECTM_SUCCESS; |
| } |
| |
| void |
| projectM::destroyPresetTools() |
| { |
| if (m_presetPos) |
| delete (m_presetPos); |
| |
| m_presetPos = 0; |
| |
| if (m_presetChooser) |
| delete (m_presetChooser); |
| |
| m_presetChooser = 0; |
| |
| if (m_presetLoader) |
| delete (m_presetLoader); |
| |
| m_presetLoader = 0; |
| } |
| |
| /// @bug queuePreset case isn't handled |
| void |
| projectM::removePreset (unsigned int index) |
| { |
| unsigned int chooserIndex = **m_presetPos; |
| |
| m_presetLoader->removePreset (index); |
| |
| // Case: no more presets, set iterator to end |
| if (m_presetChooser->empty()) |
| *m_presetPos = m_presetChooser->end(); |
| |
| // Case: chooser index has become one less due to removal of an index below it |
| else if (chooserIndex > index) { |
| chooserIndex--; |
| *m_presetPos = m_presetChooser->begin (chooserIndex); |
| } |
| |
| // Case: we have deleted the active preset position |
| // Set iterator to end of chooser |
| else if (chooserIndex == index) { |
| *m_presetPos = m_presetChooser->end(); |
| } |
| } |
| |
| unsigned int |
| projectM::addPresetURL ( |
| const std::string & presetURL, |
| const std::string & presetName, |
| const RatingList & ratings |
| ) |
| { |
| bool restorePosition = false; |
| |
| if (*m_presetPos == m_presetChooser->end()) |
| restorePosition = true; |
| |
| int index = m_presetLoader->addPresetURL (presetURL, presetName, ratings); |
| |
| if (restorePosition) |
| *m_presetPos = m_presetChooser->end(); |
| |
| return index; |
| } |
| |
| void |
| projectM::selectPreset (unsigned int index, bool hardCut) |
| { |
| if (m_presetChooser->empty()) |
| return; |
| |
| if (!hardCut) { |
| timeKeeper->StartSmoothing(); |
| } |
| |
| *m_presetPos = m_presetChooser->begin (index); |
| |
| if (!hardCut) { |
| switchPreset (m_activePreset2); |
| } else { |
| switchPreset (m_activePreset); |
| timeKeeper->StartPreset(); |
| } |
| |
| presetSwitchedEvent (hardCut, **m_presetPos); |
| } |
| |
| |
| void |
| projectM::selectRandom (const bool hardCut) |
| { |
| if (m_presetChooser->empty()) |
| return; |
| |
| if (!hardCut) { |
| timeKeeper->StartSmoothing(); |
| } |
| |
| *m_presetPos = m_presetChooser->weightedRandom (hardCut); |
| |
| if (!hardCut) { |
| switchPreset (m_activePreset2); |
| } else { |
| switchPreset (m_activePreset); |
| timeKeeper->StartPreset(); |
| } |
| |
| presetSwitchedEvent (hardCut, **m_presetPos); |
| } |
| |
| void |
| projectM::selectPrevious (const bool hardCut) |
| { |
| if (m_presetChooser->empty()) |
| return; |
| |
| if (!hardCut) { |
| timeKeeper->StartSmoothing(); |
| } |
| |
| m_presetChooser->previousPreset (*m_presetPos); |
| |
| if (!hardCut) { |
| switchPreset (m_activePreset2); |
| } else { |
| switchPreset (m_activePreset); |
| timeKeeper->StartPreset(); |
| } |
| |
| presetSwitchedEvent (hardCut, **m_presetPos); |
| |
| // m_activePreset = m_presetPos->allocate(); |
| // renderer->SetPipeline (m_activePreset->pipeline()); |
| // renderer->setPresetName (m_activePreset->name()); |
| |
| //timeKeeper->StartPreset(); |
| } |
| |
| void |
| projectM::selectNext (const bool hardCut) |
| { |
| if (m_presetChooser->empty()) |
| return; |
| |
| if (!hardCut) { |
| timeKeeper->StartSmoothing(); |
| std::cout << "start smoothing" << std::endl; |
| } |
| |
| m_presetChooser->nextPreset (*m_presetPos); |
| |
| if (!hardCut) { |
| switchPreset (m_activePreset2); |
| } else { |
| switchPreset (m_activePreset); |
| timeKeeper->StartPreset(); |
| } |
| presetSwitchedEvent (hardCut, **m_presetPos); |
| } |
| |
| /** |
| * |
| * @param targetPreset |
| */ |
| void |
| projectM::switchPreset (std::auto_ptr<Preset> & targetPreset) |
| { |
| |
| #ifdef SYNC_PRESET_SWITCHES |
| pthread_mutex_lock (&preset_mutex); |
| #endif |
| |
| targetPreset = m_presetPos->allocate(); |
| |
| // Set preset name here- event is not done because at the moment this function is oblivious to smooth/hard switches |
| renderer->setPresetName (targetPreset->name()); |
| renderer->SetPipeline (targetPreset->pipeline()); |
| |
| #ifdef SYNC_PRESET_SWITCHES |
| pthread_mutex_unlock (&preset_mutex); |
| #endif |
| } |
| |
| void |
| projectM::setPresetLock (bool isLocked) |
| { |
| renderer->noSwitch = isLocked; |
| } |
| |
| bool |
| projectM::isPresetLocked() const |
| { |
| return renderer->noSwitch; |
| } |
| |
| std::string |
| projectM::getPresetURL (unsigned int index) const |
| { |
| return m_presetLoader->getPresetURL (index); |
| } |
| |
| int |
| projectM::getPresetRating (unsigned int index, const PresetRatingType ratingType) const |
| { |
| return m_presetLoader->getPresetRating (index, ratingType); |
| } |
| |
| std::string |
| projectM::getPresetName (unsigned int index) const |
| { |
| return m_presetLoader->getPresetName (index); |
| } |
| |
| void |
| projectM::clearPlaylist() |
| { |
| m_presetLoader->clear(); |
| *m_presetPos = m_presetChooser->end(); |
| } |
| |
| void |
| projectM::selectPresetPosition (unsigned int index) |
| { |
| *m_presetPos = m_presetChooser->begin (index); |
| } |
| |
| bool |
| projectM::selectedPresetIndex (unsigned int & index) const |
| { |
| if (*m_presetPos == m_presetChooser->end()) |
| return false; |
| |
| index = **m_presetPos; |
| return true; |
| } |
| |
| |
| bool |
| projectM::presetPositionValid() const |
| { |
| return (*m_presetPos != m_presetChooser->end()); |
| } |
| |
| unsigned int |
| projectM::getPlaylistSize() const |
| { |
| return m_presetLoader->size(); |
| } |
| |
| void |
| projectM::changePresetRating (unsigned int index, int rating, const PresetRatingType ratingType) |
| { |
| m_presetLoader->setRating (index, rating, ratingType); |
| presetRatingChanged (index, rating, ratingType); |
| } |
| |
| void |
| projectM::insertPresetURL ( |
| unsigned int index, |
| const std::string & presetURL, |
| const std::string & presetName, |
| const RatingList & ratings) |
| { |
| bool atEndPosition = false; |
| int newSelectedIndex; |
| |
| if (*m_presetPos == m_presetChooser->end()) // Case: preset not selected |
| { |
| atEndPosition = true; |
| } |
| else if (**m_presetPos < index) // Case: inserting before selected preset |
| { |
| newSelectedIndex = **m_presetPos; |
| } |
| else if (**m_presetPos > index) // Case: inserting after selected preset |
| { |
| newSelectedIndex++; |
| } |
| else // Case: inserting at selected preset |
| { |
| newSelectedIndex++; |
| } |
| |
| m_presetLoader->insertPresetURL (index, presetURL, presetName, ratings); |
| |
| if (atEndPosition) |
| *m_presetPos = m_presetChooser->end(); |
| else |
| *m_presetPos = m_presetChooser->begin (newSelectedIndex); |
| } |
| |
| void |
| projectM::changePresetName (unsigned int index, std::string name) |
| { |
| m_presetLoader->setPresetName (index, name); |
| } |
| |
| |
| void |
| projectM::changeTextureSize (int size) |
| { |
| _settings.textureSize = size; |
| |
| delete renderer; |
| renderer = new Renderer (_settings.windowWidth, _settings.windowHeight, |
| _settings.meshX, _settings.meshY, |
| _settings.textureSize, |
| beatDetect, |
| _settings.presetURL, |
| _settings.titleFontURL, |
| _settings.menuFontURL); |
| } |
| |
| void |
| projectM::changePresetDuration (int seconds) |
| { |
| timeKeeper->ChangePresetDuration (seconds); |
| } |