@@ -67,6 +67,10 @@ pthread_mutex_t preset_mutex;
6767#endif
6868#endif
6969
70+ namespace {
71+ constexpr int kMaxSwitchRetries = 10 ;
72+ }
73+
7074projectM::~projectM ()
7175{
7276#ifdef USE_THREADS
@@ -779,7 +783,9 @@ void projectM::selectPreset(unsigned int index, bool hardCut)
779783 populatePresetMenu ();
780784
781785 *m_presetPos = m_presetChooser->begin (index);
782- switchPreset (hardCut);
786+ if (!startPresetTransition (hardCut)) {
787+ selectRandom (hardCut);
788+ }
783789}
784790
785791// populatePresetMenu is called when a preset is loaded.
@@ -809,44 +815,48 @@ void projectM::populatePresetMenu()
809815 }
810816 }
811817}
812- void projectM::switchPreset (const bool hardCut) {
813- std::string result;
814818
815- if (!hardCut) {
816- result = switchPreset (m_activePreset2);
817- } else {
818- result = switchPreset (m_activePreset);
819- if (result.empty ())
820- timeKeeper->StartPreset ();
821- }
819+ bool projectM::startPresetTransition (bool hard_cut) {
820+ std::unique_ptr<Preset> new_preset = switchToCurrentPreset ();
821+ if (new_preset == nullptr ) {
822+ presetSwitchFailedEvent (hard_cut, **m_presetPos, " fake error" );
823+ errorLoadingCurrentPreset = true ;
824+ populatePresetMenu ();
825+ return false ;
826+ }
822827
823- if (result.empty () && !hardCut) {
824- timeKeeper->StartSmoothing ();
825- }
828+ if (hard_cut) {
829+ m_activePreset = std::move (new_preset);
830+ timeKeeper->StartPreset ();
831+ } else {
832+ m_activePreset2 = std::move (new_preset);
833+ timeKeeper->StartPreset ();
834+ timeKeeper->StartSmoothing ();
835+ }
826836
827- if (result.empty ()) {
828- presetSwitchedEvent (hardCut, **m_presetPos);
829- errorLoadingCurrentPreset = false ;
830- } else {
831- presetSwitchFailedEvent (hardCut, **m_presetPos, result);
832- errorLoadingCurrentPreset = true ;
833- }
837+ presetSwitchedEvent (hard_cut, **m_presetPos);
838+ errorLoadingCurrentPreset = false ;
834839
835- populatePresetMenu ();
836- }
840+ populatePresetMenu ();
837841
842+ return true ;
843+ }
838844
839845void projectM::selectRandom (const bool hardCut) {
840846 if (m_presetChooser->empty ())
841847 return ;
842848 presetHistory.push_back (m_presetPos->lastIndex ());
849+
850+ for (int i = 0 ; i < kMaxSwitchRetries ; ++i) {
851+ *m_presetPos = m_presetChooser->weightedRandom (hardCut);
852+ if (startPresetTransition (hardCut)) {
853+ break ;
854+ }
855+ }
843856 // If presetHistory is tracking more than 10, then delete the oldest entry so we cap to a history of 10.
844857 if (presetHistory.size () >= 10 )
845858 presetHistory.erase (presetHistory.begin ());
846859 presetFuture.clear ();
847- *m_presetPos = m_presetChooser->weightedRandom (hardCut);
848-
849- switchPreset (hardCut);
850860
851861}
852862
@@ -860,11 +870,13 @@ void projectM::selectPrevious(const bool hardCut) {
860870 presetHistory.pop_back ();
861871 }
862872 else {
863- // if we are not shuffling or there is no random future history, then let's not track a random vector and move fowards in the preset index.
873+ // if we are not shuffling or there is no random future history, then let's not track a random vector and move backwards in the preset index.
864874 presetHistory.clear ();
865875 presetFuture.clear ();
866876 m_presetChooser->previousPreset (*m_presetPos);
867- switchPreset (hardCut);
877+ if (!startPresetTransition (hardCut)) {
878+ selectRandom (hardCut);
879+ }
868880 }
869881}
870882
@@ -877,45 +889,52 @@ void projectM::selectNext(const bool hardCut) {
877889 presetFuture.pop_back ();
878890 }
879891 else {
880- // if we are not shuffling or there is no random history, then let's not track a random vector and move backwards in the preset index.
892+ // if we are not shuffling or there is no random history, then let's not track a random vector and move forwards in the preset index.
881893 presetFuture.clear ();
882894 presetHistory.clear ();
883895 m_presetChooser->nextPreset (*m_presetPos);
884- switchPreset (hardCut);
896+ if (!startPresetTransition (hardCut)) {
897+ selectRandom (hardCut);
898+ }
885899 }
886900}
887901
888902/* *
889- * Switches to the target preset.
890- * @param targetPreset
891- * @return a message indicating an error, empty otherwise.
892- */
893- std::string projectM::switchPreset (std::unique_ptr<Preset> & targetPreset) {
894-
895- std::string result;
896-
903+ * Switches the pipeline and renderer to the current preset.
904+ * @return the resulting Preset object, or nullptr on failure.
905+ */
906+ std::unique_ptr<Preset> projectM::switchToCurrentPreset () {
907+ std::unique_ptr<Preset> new_preset;
897908#ifdef SYNC_PRESET_SWITCHES
898- pthread_mutex_lock (&preset_mutex);
909+ pthread_mutex_lock (&preset_mutex);
899910#endif
900- try {
901- targetPreset = m_presetPos->allocate ();
902- } catch (const PresetFactoryException & e) {
911+ try {
912+ new_preset = m_presetPos->allocate ();
913+ } catch (const PresetFactoryException &e) {
914+ std::cerr << " problem allocating target preset: " << e.message ()
915+ << std::endl;
916+ }
917+
918+ if (new_preset == nullptr ) {
903919#ifdef SYNC_PRESET_SWITCHES
904- pthread_mutex_unlock (&preset_mutex);
920+ pthread_mutex_unlock (&preset_mutex);
905921#endif
906- std::cerr << " problem allocating target preset: " << e.message () << std::endl;
907- return e.message ();
908- }
909-
910- // Set preset name here- event is not done because at the moment this function is oblivious to smooth/hard switches
911- renderer->setPresetName (targetPreset->name ());
912- result = renderer->SetPipeline (targetPreset->pipeline ());
922+ std::cerr << " Could not switch to current preset" << std::endl;
923+ return nullptr ;
924+ }
925+
926+ // Set preset name here- event is not done because at the moment this function
927+ // is oblivious to smooth/hard switches
928+ renderer->setPresetName (new_preset->name ());
929+ std::string result = renderer->SetPipeline (new_preset->pipeline ());
930+ if (!result.empty ()) {
931+ std::cerr << " problem setting pipeline: " << result << std::endl;
932+ }
913933
914934#ifdef SYNC_PRESET_SWITCHES
915- pthread_mutex_unlock (&preset_mutex);
935+ pthread_mutex_unlock (&preset_mutex);
916936#endif
917-
918- return result;
937+ return new_preset;
919938}
920939
921940void projectM::setPresetLock ( bool isLocked )
0 commit comments