gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

commit 7834d9f3cf6fa4d43ff2cd372e460c1201f2de9c
parent fa0c6884f5dce6a77c470581e1d0cc7f1d2947af
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Thu, 24 Oct 2024 14:11:21 +0200

support user documents folder for skins

Diffstat:
Mdoc/changelog.txt | 8++++++++
Msource/jucePluginEditorLib/pluginEditor.cpp | 3++-
Msource/jucePluginEditorLib/pluginEditorState.cpp | 52++++++++++++++++++++++++++++++++--------------------
Msource/jucePluginEditorLib/pluginEditorState.h | 3++-
Msource/jucePluginLib/tools.cpp | 7+++++++
Msource/jucePluginLib/tools.h | 4++++
6 files changed, 55 insertions(+), 22 deletions(-)

diff --git a/doc/changelog.txt b/doc/changelog.txt @@ -12,6 +12,14 @@ Framework: file browser - [Imp] All MacOS builds now included a script to remove quaratine attributes +- [Imp] The default skin folder has changed. Custom skins are now supposed to be in: + + c:\Users\<username>\Documents\<synthname>\skins (Win) + ~/Documents/<synthname>/skins (Mac) + [XDG_DATA_HOME or ~/.local/share]/<synthname>/skins (Linux) + + Existing skins in the old location are still supported to ensure backwards + compatibility NodalRed2x: diff --git a/source/jucePluginEditorLib/pluginEditor.cpp b/source/jucePluginEditorLib/pluginEditor.cpp @@ -564,7 +564,8 @@ namespace jucePluginEditorLib return res; const auto modulePath = synthLib::getModulePath(); - const auto folder = synthLib::validatePath(m_skinFolder.find(modulePath) == 0 ? m_skinFolder : modulePath + m_skinFolder); + const auto publicDataPath = pluginLib::Tools::getPublicDataFolder(m_processor.getProperties().name); + const auto folder = synthLib::validatePath(m_skinFolder.find(modulePath) == 0 || m_skinFolder.find(publicDataPath) == 0 ? m_skinFolder : modulePath + m_skinFolder); // try to load from disk first FILE* hFile = fopen((folder + _name).c_str(), "rb"); diff --git a/source/jucePluginEditorLib/pluginEditorState.cpp b/source/jucePluginEditorLib/pluginEditorState.cpp @@ -10,11 +10,12 @@ #include "dsp56kEmu/logging.h" +#include "jucePluginLib/tools.h" + namespace jucePluginEditorLib { PluginEditorState::PluginEditorState(Processor& _processor, pluginLib::Controller& _controller, std::vector<Skin> _includedSkins) : m_processor(_processor), m_parameterBinding(_controller), m_includedSkins(std::move(_includedSkins)) - , m_skinFolderName("skins_" + _processor.getProperties().name) { } @@ -80,6 +81,11 @@ void PluginEditorState::getPerInstanceConfig(std::vector<uint8_t>& _data) _data.insert(_data.end(), m_instanceConfig.begin(), m_instanceConfig.end()); } +std::string PluginEditorState::getSkinFolder() const +{ + return pluginLib::Tools::getPublicDataFolder(m_processor.getProperties().name) + "skins/"; +} + void PluginEditorState::loadSkin(const Skin& _skin) { m_currentSkin = _skin; @@ -178,8 +184,14 @@ void PluginEditorState::openMenu(const juce::MouseEvent* _event) // find more skins on disk const auto modulePath = synthLib::getModulePath(); + // new: user documents folder std::vector<std::string> entries; - synthLib::getDirectoryEntries(entries, modulePath + m_skinFolderName); + synthLib::getDirectoryEntries(entries, getSkinFolder()); + + // old: next to plugin, kept for backwards compatibility + std::vector<std::string> entriesModulePath; + synthLib::getDirectoryEntries(entriesModulePath, modulePath + "skins_" + m_processor.getProperties().name); + entries.insert(entries.end(), entriesModulePath.begin(), entriesModulePath.end()); for (const auto& entry : entries) { @@ -196,12 +208,14 @@ void PluginEditorState::openMenu(const juce::MouseEvent* _event) skinMenu.addSeparator(); } - const auto relativePath = entry.substr(modulePath.size()); + std::string skinPath = entry; + if(entry.find(modulePath) == 0) + skinPath = entry.substr(modulePath.size()); auto jsonName = file; const auto pathEndPos = jsonName.find_last_of("/\\"); if(pathEndPos != std::string::npos) jsonName = file.substr(pathEndPos+1); - const Skin skin{jsonName.substr(0, jsonName.length() - 5), jsonName, relativePath}; + const Skin skin{jsonName.substr(0, jsonName.length() - 5), jsonName, skinPath}; addSkinEntry(skin); } } @@ -210,25 +224,23 @@ void PluginEditorState::openMenu(const juce::MouseEvent* _event) if(!loadedSkinIsPartOfList) addSkinEntry(getCurrentSkin()); - if(m_editor && m_currentSkin.folder.empty() || m_currentSkin.folder.find(m_skinFolderName) == std::string::npos) + skinMenu.addSeparator(); + + if(getEditor() && m_currentSkin.folder.empty() || m_currentSkin.folder.find(getSkinFolder()) != 0) { - auto* editor = getEditor(); - if(editor) + skinMenu.addItem("Export current skin to folder '" + getSkinFolder() + "' on disk", true, false, [this] { - skinMenu.addSeparator(); - skinMenu.addItem("Export current skin to folder '" + m_skinFolderName + "' on disk", true, false, [this] - { - exportCurrentSkin(); - }); - skinMenu.addItem("Open folder '" + m_skinFolderName + "' in File Browser", true, false, [this] - { - const auto dir = synthLib::getModulePath() + m_skinFolderName; - synthLib::createDirectory(dir); - juce::File(dir).revealToUser(); - }); - } + exportCurrentSkin(); + }); } + skinMenu.addItem("Open folder '" + getSkinFolder() + "' in File Browser", true, false, [this] + { + const auto dir = getSkinFolder(); + synthLib::createDirectory(dir); + juce::File(dir).revealToUser(); + }); + juce::PopupMenu scaleMenu; scaleMenu.addItem("50%", true, scale == 50, [this] { setGuiScale(50); }); scaleMenu.addItem("65%", true, scale == 65, [this] { setGuiScale(65); }); @@ -430,7 +442,7 @@ void PluginEditorState::exportCurrentSkin() const if(!editor) return; - const auto res = editor->exportToFolder(synthLib::getModulePath() + m_skinFolderName + '/'); + const auto res = editor->exportToFolder(getSkinFolder()); if(!res.empty()) { diff --git a/source/jucePluginEditorLib/pluginEditorState.h b/source/jucePluginEditorLib/pluginEditorState.h @@ -71,6 +71,8 @@ namespace jucePluginEditorLib void setPerInstanceConfig(const std::vector<uint8_t>& _data); void getPerInstanceConfig(std::vector<uint8_t>& _data); + std::string getSkinFolder() const; + protected: virtual Editor* createEditor(const Skin& _skin) = 0; @@ -88,6 +90,5 @@ namespace jucePluginEditorLib float m_rootScale = 1.0f; std::vector<Skin> m_includedSkins; std::vector<uint8_t> m_instanceConfig; - std::string m_skinFolderName; }; } diff --git a/source/jucePluginLib/tools.cpp b/source/jucePluginLib/tools.cpp @@ -3,6 +3,8 @@ #include "juce_audio_processors/juce_audio_processors.h" #include "juce_gui_basics/juce_gui_basics.h" +#include "synthLib/os.h" + namespace pluginLib { bool Tools::isHeadless() @@ -18,4 +20,9 @@ namespace pluginLib // build machine, whatever that is good for return host.contains("juce_vst3_helper") || host.contains("juce_lv2_helper"); } + + std::string Tools::getPublicDataFolder(const std::string& _productName) + { + return synthLib::getSpecialFolderPath(synthLib::SpecialFolderType::UserDocuments) + _productName + '/'; + } } diff --git a/source/jucePluginLib/tools.h b/source/jucePluginLib/tools.h @@ -1,10 +1,14 @@ #pragma once +#include <string> + namespace pluginLib { class Tools { public: static bool isHeadless(); + + static std::string getPublicDataFolder(const std::string& _productName); }; }