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:
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);
};
}