diff --git a/src/ProjectMSDLApplication.cpp b/src/ProjectMSDLApplication.cpp index 8f8bb97..0cf9d3d 100644 --- a/src/ProjectMSDLApplication.cpp +++ b/src/ProjectMSDLApplication.cpp @@ -76,7 +76,6 @@ void ProjectMSDLApplication::initialize(Poco::Util::Application& self) { loadConfiguration(configFilePath.toString(), PRIO_DEFAULT); } - } } } @@ -202,6 +201,14 @@ void ProjectMSDLApplication::defineOptions(Poco::Util::OptionSet& options) false, "<0/1>", true) .binding("projectM.shuffleEnabled", _commandLineOverrides)); + options.addOption(Option("skipToDropped", "", "Skip to drag & dropped presets", + false, "<0/1>", true) + .binding("projectM.skipToDropped", _commandLineOverrides)); + + options.addOption(Option("droppedFolderOverride", "", "When dropping a folder, clear the playlist and add all presets from the folder.", + false, "<0/1>", true) + .binding("projectM.droppedFolderOverride", _commandLineOverrides)); + options.addOption(Option("presetDuration", "", "Preset duration. Any number > 1, default 30.", false, "", true) .binding("projectM.displayDuration", _commandLineOverrides)); @@ -273,4 +280,3 @@ void ProjectMSDLApplication::ListAudioDevices(POCO_UNUSED const std::string& nam { _commandLineOverrides->setBool("audio.listDevices", true); } - diff --git a/src/RenderLoop.cpp b/src/RenderLoop.cpp index 8a8fbf1..1fe8fa1 100644 --- a/src/RenderLoop.cpp +++ b/src/RenderLoop.cpp @@ -10,6 +10,8 @@ #include +#include "ProjectMSDLApplication.h" + RenderLoop::RenderLoop() : _audioCapture(Poco::Util::Application::instance().getSubsystem()) , _projectMWrapper(Poco::Util::Application::instance().getSubsystem()) @@ -17,6 +19,7 @@ RenderLoop::RenderLoop() , _projectMHandle(_projectMWrapper.ProjectM()) , _playlistHandle(_projectMWrapper.Playlist()) , _projectMGui(Poco::Util::Application::instance().getSubsystem()) + , _userConfig(ProjectMSDLApplication::instance().UserConfiguration()) { } @@ -103,6 +106,94 @@ void RenderLoop::PollEvents() break; + case SDL_DROPFILE: { + char* droppedFilePath = event.drop.file; + + // first we want to get the config settings that are relevant ehre + // namely skipToDropped and droppedFolderOverride + // we can get them from the projectMWrapper, in the _projectMConfigView available on it + bool skipToDropped = _userConfig->getBool("projectM.skipToDropped", true); + bool droppedFolderOverride = _userConfig->getBool("projectM.droppedFolderOverride", false); + + + bool shuffle = projectm_playlist_get_shuffle(_playlistHandle); + if (shuffle && skipToDropped) + { + // if shuffle is enabled, we disable it temporarily, so the dropped preset is played next + // if skipToDropped is false, we also keep shuffle enabled, as it doesn't matter since the current preset is unaffected + projectm_playlist_set_shuffle(_playlistHandle, false); + } + + int index = projectm_playlist_get_position(_playlistHandle) + 1; + + do + { + Poco::File droppedFile(droppedFilePath); + if (!droppedFile.isDirectory()) + { + // handle dropped preset file + Poco::Path droppedFileP(droppedFilePath); + if (!droppedFile.exists() || (droppedFileP.getExtension() != "milk" && droppedFileP.getExtension() != "prjm")) + { + std::string toastMessage = std::string("Invalid preset file: ") + droppedFilePath; + Poco::NotificationCenter::defaultCenter().postNotification(new DisplayToastNotification(toastMessage)); + poco_information_f1(_logger, "%s", toastMessage); + break; // exit the block and go to the shuffle check + } + + if (projectm_playlist_insert_preset(_playlistHandle, droppedFilePath, index, true)) + { + if (skipToDropped) + { + projectm_playlist_play_next(_playlistHandle, true); + } + poco_information_f1(_logger, "Added preset: %s", std::string(droppedFilePath)); + // no need to toast single presets, as its obvious if a preset was loaded. + } + } + else + { + // handle dropped directory + + // if droppedFolderOverride is enabled, we clear the playlist first + // current edge case: if the dropped directory is invalid or contains no presets, then it still clears the playlist + if (droppedFolderOverride) + { + projectm_playlist_clear(_playlistHandle); + index = 0; + } + + uint32_t addedFilesCount = projectm_playlist_insert_path(_playlistHandle, droppedFilePath, index, true, true); + if (addedFilesCount > 0) + { + std::string toastMessage = "Added " + std::to_string(addedFilesCount) + " presets from " + droppedFilePath; + poco_information_f1(_logger, "%s", toastMessage); + if (skipToDropped || droppedFolderOverride) + { + // if skip to dropped is true, or if a folder was dropped and it overrode the playlist, we skip to the next preset + projectm_playlist_play_next(_playlistHandle, true); + } + Poco::NotificationCenter::defaultCenter().postNotification(new DisplayToastNotification(toastMessage)); + } + else + { + std::string toastMessage = std::string("No presets found in: ") + droppedFilePath; + Poco::NotificationCenter::defaultCenter().postNotification(new DisplayToastNotification(toastMessage)); + poco_information_f1(_logger, "%s", toastMessage); + } + } + } while (false); + + if (shuffle && skipToDropped) + { + projectm_playlist_set_shuffle(_playlistHandle, true); + } + + SDL_free(droppedFilePath); + break; + } + + case SDL_QUIT: _wantsToQuit = true; break; diff --git a/src/RenderLoop.h b/src/RenderLoop.h index 2c39054..8a63949 100644 --- a/src/RenderLoop.h +++ b/src/RenderLoop.h @@ -87,5 +87,7 @@ class RenderLoop ModifierKeyStates _keyStates; //!< Current "pressed" states of modifier keys + Poco::AutoPtr _userConfig; //!< View of the "projectM" configuration subkey in the "user" configuration. + Poco::Logger& _logger{Poco::Logger::get("RenderLoop")}; //!< The class logger. }; diff --git a/src/gui/SettingsWindow.cpp b/src/gui/SettingsWindow.cpp index 121a736..aec27a5 100644 --- a/src/gui/SettingsWindow.cpp +++ b/src/gui/SettingsWindow.cpp @@ -105,6 +105,14 @@ void SettingsWindow::DrawProjectMSettingsTab() LabelWithTooltip("Shuffle Presets", "Selects presets randomly from the current playlist."); BooleanSetting("projectM.shuffleEnabled", true); + ImGui::TableNextRow(); + LabelWithTooltip("Skip To Dropped Presets", "If enabled, will skip to the new presets when preset(s) are dropped onto the window and added to the playlist"); + BooleanSetting("projectM.skipToDropped", true); + + ImGui::TableNextRow(); + LabelWithTooltip("Dropped Folder Overrides Playlist", "When dropping a folder, clear the playlist and add all presets from the folder."); + BooleanSetting("projectM.droppedFolderOverride", false); + ImGui::TableNextRow(); LabelWithTooltip("Preset Display Duration", "Time in seconds a preset will be displayed before it's switched."); DoubleSetting("projectM.displayDuration", 30.0, 1.0, 240.0);