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