From 0cb1b67bfab45963440d3cde36e875bfc1591019 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Wed, 9 Dec 2020 15:40:42 +0100 Subject: [PATCH 1/4] Use a custom SFZ path set in user configuration --- vst/SfizzFileScan.cpp | 64 ++++++++++++++++++++++++--------------- vst/SfizzFileScan.h | 7 +++-- vst/SfizzVstProcessor.cpp | 13 +++++++- 3 files changed, 57 insertions(+), 27 deletions(-) diff --git a/vst/SfizzFileScan.cpp b/vst/SfizzFileScan.cpp index 9971d6ab..a56f2e4a 100644 --- a/vst/SfizzFileScan.cpp +++ b/vst/SfizzFileScan.cpp @@ -6,10 +6,10 @@ #include "SfizzFileScan.h" #include "SfizzForeignPaths.h" +#include "SfizzSettings.h" #include "NativeHelpers.h" #include #include -#include #include // wait at least this much before refreshing the file rescan @@ -63,7 +63,7 @@ void SfzFileScan::refreshScan(bool force) FileTrieBuilder builder; - for (const fs::path& dirPath : SfizzPaths::sfzDefaultPaths()) { + for (const fs::path& dirPath : SfizzPaths::getSfzSearchPaths()) { std::error_code ec; const fs::directory_options dirOpts = fs::directory_options::skip_permission_denied; @@ -183,36 +183,52 @@ const fs::path& SfzFileScan::electBestMatch(const fs::path& path, absl::Span sfzDefaultPaths() +std::vector getSfzSearchPaths() { - static const auto paths = []() -> std::vector { - std::vector paths; - paths.reserve(8); - auto addPath = [&paths](const fs::path& newPath) { - if (absl::c_find(paths, newPath) == paths.end()) - paths.push_back(newPath); - }; + std::vector paths; + paths.reserve(8); + auto addPath = [&paths](const fs::path& newPath) { + if (absl::c_find(paths, newPath) == paths.end()) + paths.push_back(newPath); + }; - addPath(getUserDocumentsDirectory() / "SFZ instruments"); + absl::optional configDefaultPath = getSfzConfigDefaultPath(); + fs::path fallbackDefaultPath = getSfzFallbackDefaultPath(); - for (const fs::path& foreign : { - getAriaPathSetting("user_files_dir"), - getAriaPathSetting("Converted_path") }) - if (!foreign.empty() && foreign.is_absolute()) - addPath(foreign); + if (configDefaultPath) + addPath(*configDefaultPath); + addPath(fallbackDefaultPath); - paths.shrink_to_fit(); - return paths; - }(); + for (const fs::path& foreign : { + getAriaPathSetting("user_files_dir"), + getAriaPathSetting("Converted_path") }) + if (!foreign.empty() && foreign.is_absolute()) + addPath(foreign); + + paths.shrink_to_fit(); return paths; } -void createSfzDefaultPaths() +absl::optional getSfzConfigDefaultPath() { - for (const fs::path& path : sfzDefaultPaths()) { - std::error_code ec; - fs::create_directory(path, ec); - } + SfizzSettings settings; + fs::path path = fs::u8path(settings.load_or("user_files_dir", {})); + if (path.empty() || !path.is_absolute()) + return {}; + return std::move(path); +} + +void setSfzConfigDefaultPath(const fs::path& path) +{ + if (path.empty() || !path.is_absolute()) + return; + SfizzSettings settings; + settings.store("user_files_dir", path.u8string()); +} + +fs::path getSfzFallbackDefaultPath() +{ + return getUserDocumentsDirectory() / "SFZ instruments"; } } // namespace SfizzPaths diff --git a/vst/SfizzFileScan.h b/vst/SfizzFileScan.h index 2626ef15..19dabf56 100644 --- a/vst/SfizzFileScan.h +++ b/vst/SfizzFileScan.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,8 @@ private: }; namespace SfizzPaths { -absl::Span sfzDefaultPaths(); -void createSfzDefaultPaths(); +std::vector getSfzSearchPaths(); +absl::optional getSfzConfigDefaultPath(); +void setSfzConfigDefaultPath(const fs::path& path); +fs::path getSfzFallbackDefaultPath(); } // namespace SfizzPaths diff --git a/vst/SfizzVstProcessor.cpp b/vst/SfizzVstProcessor.cpp index 77de7c43..708979eb 100644 --- a/vst/SfizzVstProcessor.cpp +++ b/vst/SfizzVstProcessor.cpp @@ -38,7 +38,18 @@ SfizzVstProcessor::SfizzVstProcessor() { setControllerClass(SfizzVstController::cid); - SfizzPaths::createSfzDefaultPaths(); + // ensure the SFZ path exists: + // the one specified in the configuration, otherwise the fallback + absl::optional configDefaultPath = SfizzPaths::getSfzConfigDefaultPath(); + if (configDefaultPath) { + std::error_code ec; + fs::create_directory(*configDefaultPath, ec); + } + else { + fs::path fallbackDefaultPath = SfizzPaths::getSfzFallbackDefaultPath(); + std::error_code ec; + fs::create_directory(fallbackDefaultPath, ec); + } } SfizzVstProcessor::~SfizzVstProcessor() From ccdba9d6c7bd11d29296c0b74f0ea8e0281f5427 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Wed, 9 Dec 2020 16:27:15 +0100 Subject: [PATCH 2/4] Add ability in the editor to change the user directory --- editor/layout/main.fl | 25 ++++++++++++++--- editor/src/editor/EditIds.h | 2 ++ editor/src/editor/Editor.cpp | 45 +++++++++++++++++++++++++++++++ editor/src/editor/layout/main.hpp | 18 +++++++++---- lv2/sfizz_ui.cpp | 4 +++ vst/SfizzVstEditor.cpp | 9 +++++++ 6 files changed, 94 insertions(+), 9 deletions(-) diff --git a/editor/layout/main.fl b/editor/layout/main.fl index 59d22a06..59ed5298 100644 --- a/editor/layout/main.fl +++ b/editor/layout/main.fl @@ -11,7 +11,7 @@ widget_class mainView {open class Background } Fl_Group {} { - comment {theme=darkTheme} open + comment {theme=darkTheme} xywh {0 0 800 110} class LogicalGroup } { @@ -138,7 +138,7 @@ widget_class mainView {open } } Fl_Group {subPanels_[kPanelGeneral]} { - xywh {5 110 791 285} + xywh {5 110 791 285} hide class LogicalGroup } { Fl_Group {} {open @@ -213,7 +213,7 @@ widget_class mainView {open } } Fl_Group {subPanels_[kPanelSettings]} {open - xywh {5 109 790 286} hide + xywh {5 109 790 316} class LogicalGroup } { Fl_Group {} { @@ -304,8 +304,25 @@ widget_class mainView {open class ValueMenu } } + Fl_Group userFilesGroup_ { + label Files open selected + xywh {620 270 139 100} box ROUNDED_BOX labelsize 12 align 17 + class TitleGroup + } { + Fl_Box {} { + label {User SFZ folder} + xywh {640 290 100 25} labelsize 12 + class ValueLabel + } + Fl_Button userFilesDirButton_ { + label DefaultPath + comment {tag=kTagChooseUserFilesDir} + xywh {640 330 100 25} labelsize 12 + class ValueButton + } + } } - Fl_Box piano_ {selected + Fl_Box piano_ { xywh {5 400 790 70} labelsize 12 class Piano } diff --git a/editor/src/editor/EditIds.h b/editor/src/editor/EditIds.h index 660853db..8645210a 100644 --- a/editor/src/editor/EditIds.h +++ b/editor/src/editor/EditIds.h @@ -17,6 +17,8 @@ enum class EditId : int { ScalaRootKey, TuningFrequency, StretchTuning, + CanEditUserFilesDir, + UserFilesDir, UINumCurves, UINumMasters, UINumGroups, diff --git a/editor/src/editor/Editor.cpp b/editor/src/editor/Editor.cpp index 5a4c5a05..f6b16897 100644 --- a/editor/src/editor/Editor.cpp +++ b/editor/src/editor/Editor.cpp @@ -63,6 +63,7 @@ struct Editor::Impl : EditorController::Receiver, IControlListener { kTagSetScalaRootKey, kTagSetTuningFrequency, kTagSetStretchedTuning, + kTagChooseUserFilesDir, kTagFirstChangePanel, kTagLastChangePanel = kTagFirstChangePanel + kNumPanels - 1, }; @@ -86,6 +87,9 @@ struct Editor::Impl : EditorController::Receiver, IControlListener { CControl *stretchedTuningSlider_ = nullptr; CTextLabel* stretchedTuningLabel_ = nullptr; + STitleContainer* userFilesGroup_ = nullptr; + STextButton* userFilesDirButton_ = nullptr; + CTextLabel* infoCurvesLabel_ = nullptr; CTextLabel* infoMastersLabel_ = nullptr; CTextLabel* infoGroupsLabel_ = nullptr; @@ -118,6 +122,7 @@ struct Editor::Impl : EditorController::Receiver, IControlListener { void changeToNextSfzFile(long offset); void chooseScalaFile(); void changeScalaFile(const std::string& filePath); + void chooseUserFilesDir(); static bool scanDirectoryFiles(const fs::path& dirPath, std::function filter, std::vector& fileNames); @@ -125,6 +130,7 @@ struct Editor::Impl : EditorController::Receiver, IControlListener { void updateSfzFileLabel(const std::string& filePath); void updateScalaFileLabel(const std::string& filePath); + void updateUserFilesDirLabel(const std::string& filePath); static void updateLabelWithFileName(CTextLabel* label, const std::string& filePath, absl::string_view removedSuffix); static void updateButtonWithFileName(STextButton* button, const std::string& filePath, absl::string_view removedSuffix); static void updateSButtonWithFileName(STextButton* button, const std::string& filePath, absl::string_view removedSuffix); @@ -268,6 +274,17 @@ void Editor::Impl::uiReceiveValue(EditId id, const EditValue& v) updateStretchedTuningLabel(value); } break; + case EditId::CanEditUserFilesDir: + { + if (STitleContainer* group = userFilesGroup_) + group->setVisible(v.to_float()); + break; + } + case EditId::UserFilesDir: + { + updateUserFilesDirLabel(v.to_string()); + break; + } case EditId::UINumCurves: { const int value = static_cast(v.to_float()); @@ -836,6 +853,22 @@ void Editor::Impl::changeScalaFile(const std::string& filePath) updateScalaFileLabel(filePath); } +void Editor::Impl::chooseUserFilesDir() +{ + SharedPointer fs = owned( + CNewFileSelector::create(frame_, CNewFileSelector::kSelectDirectory)); + + fs->setTitle("Set user files directory"); + + if (fs->runModal()) { + UTF8StringPtr dir = fs->getSelectedFile(0); + if (dir) { + updateUserFilesDirLabel(dir); + ctrl_->uiSendValue(EditId::UserFilesDir, std::string(dir)); + } + } +} + bool Editor::Impl::scanDirectoryFiles(const fs::path& dirPath, std::function filter, std::vector& fileNames) { std::error_code ec; @@ -898,6 +931,11 @@ void Editor::Impl::updateScalaFileLabel(const std::string& filePath) updateButtonWithFileName(scalaFileButton_, filePath, ".scl"); } +void Editor::Impl::updateUserFilesDirLabel(const std::string& filePath) +{ + updateButtonWithFileName(userFilesDirButton_, filePath, {}); +} + void Editor::Impl::updateLabelWithFileName(CTextLabel* label, const std::string& filePath, absl::string_view removedSuffix) { if (!label) @@ -1137,6 +1175,13 @@ void Editor::Impl::valueChanged(CControl* ctl) updateStretchedTuningLabel(value); break; + case kTagChooseUserFilesDir: + if (value != 1) + break; + + Call::later([this]() { chooseUserFilesDir(); }); + break; + default: if (tag >= kTagFirstChangePanel && tag <= kTagLastChangePanel) { int panelId = tag - kTagFirstChangePanel; diff --git a/editor/src/editor/layout/main.hpp b/editor/src/editor/layout/main.hpp index 0c9c61e2..6f4da9e3 100644 --- a/editor/src/editor/layout/main.hpp +++ b/editor/src/editor/layout/main.hpp @@ -69,6 +69,7 @@ enterTheme(defaultTheme); LogicalGroup* const view__28 = createLogicalGroup(CRect(5, 110, 796, 395), -1, "", kCenterText, 14); subPanels_[kPanelGeneral] = view__28; view__0->addView(view__28); +view__28->setVisible(false); RoundedGroup* const view__29 = createRoundedGroup(CRect(0, 0, 175, 280), -1, "", kCenterText, 14); view__28->addView(view__29); Label* const view__30 = createLabel(CRect(15, 10, 75, 35), -1, "Curves:", kLeftText, 14); @@ -104,10 +105,9 @@ RoundedGroup* const view__41 = createRoundedGroup(CRect(0, 0, 790, 285), -1, "", view__40->addView(view__41); Label* const view__42 = createLabel(CRect(0, 0, 790, 285), -1, "Controls not available", kCenterText, 40); view__41->addView(view__42); -LogicalGroup* const view__43 = createLogicalGroup(CRect(5, 109, 795, 395), -1, "", kCenterText, 14); +LogicalGroup* const view__43 = createLogicalGroup(CRect(5, 109, 795, 425), -1, "", kCenterText, 14); subPanels_[kPanelSettings] = view__43; view__0->addView(view__43); -view__43->setVisible(false); TitleGroup* const view__44 = createTitleGroup(CRect(255, 26, 535, 126), -1, "Engine", kCenterText, 12); view__43->addView(view__44); ValueMenu* const view__45 = createValueMenu(CRect(25, 60, 85, 85), kTagSetNumVoices, "", kCenterText, 12); @@ -150,6 +150,14 @@ view__51->addView(view__59); ValueMenu* const view__60 = createValueMenu(CRect(170, 60, 200, 85), kTagSetScalaRootKey, "", kCenterText, 12); scalaRootOctaveSlider_ = view__60; view__51->addView(view__60); -Piano* const view__61 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12); -piano_ = view__61; -view__0->addView(view__61); +TitleGroup* const view__61 = createTitleGroup(CRect(615, 161, 754, 261), -1, "Files", kCenterText, 12); +userFilesGroup_ = view__61; +view__43->addView(view__61); +ValueLabel* const view__62 = createValueLabel(CRect(20, 20, 120, 45), -1, "User SFZ folder", kCenterText, 12); +view__61->addView(view__62); +ValueButton* const view__63 = createValueButton(CRect(20, 60, 120, 85), kTagChooseUserFilesDir, "DefaultPath", kCenterText, 12); +userFilesDirButton_ = view__63; +view__61->addView(view__63); +Piano* const view__64 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12); +piano_ = view__64; +view__0->addView(view__64); diff --git a/lv2/sfizz_ui.cpp b/lv2/sfizz_ui.cpp index 79e3f9fa..47faf8a4 100644 --- a/lv2/sfizz_ui.cpp +++ b/lv2/sfizz_ui.cpp @@ -239,6 +239,10 @@ instantiate(const LV2UI_Descriptor *descriptor, self->editor.reset(editor); editor->open(*uiFrame); + // user files dir is not relevant to LV2 (not yet?) + // LV2 has its own path management mechanism + self->uiReceiveValue(EditId::CanEditUserFilesDir, 0); + *widget = reinterpret_cast(uiFrame->getPlatformFrame()->getPlatformRepresentation()); if (self->resize) diff --git a/vst/SfizzVstEditor.cpp b/vst/SfizzVstEditor.cpp index c04b5d1d..69bc7ace 100644 --- a/vst/SfizzVstEditor.cpp +++ b/vst/SfizzVstEditor.cpp @@ -6,6 +6,7 @@ #include "SfizzVstEditor.h" #include "SfizzVstState.h" +#include "SfizzFileScan.h" #include "editor/Editor.h" #include "editor/EditIds.h" #if !defined(__APPLE__) && !defined(_WIN32) @@ -73,6 +74,10 @@ bool PLUGIN_API SfizzVstEditor::open(void* parent, const VSTGUI::PlatformType& p editor->open(*frame); + absl::optional userFilesDir = SfizzPaths::getSfzConfigDefaultPath(); + uiReceiveValue(EditId::CanEditUserFilesDir, 1); + uiReceiveValue(EditId::UserFilesDir, userFilesDir.value_or(fs::path()).u8string()); + return true; } @@ -242,6 +247,10 @@ void SfizzVstEditor::uiSendValue(EditId id, const EditValue& v) normalizeAndSet(kPidStretchedTuning, kParamStretchedTuningRange, v.to_float()); break; + case EditId::UserFilesDir: + SfizzPaths::setSfzConfigDefaultPath(fs::u8path(v.to_string())); + break; + case EditId::UIActivePanel: uiState_.activePanel = static_cast(v.to_float()); break; From a848d8e94eb9052ae7957cc29d51a36fadc10bfd Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Wed, 9 Dec 2020 17:06:05 +0100 Subject: [PATCH 3/4] Fix the file search by filename key --- vst/SfizzFileScan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vst/SfizzFileScan.cpp b/vst/SfizzFileScan.cpp index a56f2e4a..441f9e80 100644 --- a/vst/SfizzFileScan.cpp +++ b/vst/SfizzFileScan.cpp @@ -31,7 +31,7 @@ bool SfzFileScan::locateRealFile(const fs::path& pathOrig, fs::path& pathFound) std::unique_lock lock { mutex }; refreshScan(); - auto it = file_index_.find(keyOf(pathOrig)); + auto it = file_index_.find(keyOf(pathOrig.filename())); if (it == file_index_.end()) return false; From cc24203f2d4f4d4bc5771639380d5029c88f4628 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Wed, 9 Dec 2020 17:08:27 +0100 Subject: [PATCH 4/4] Log the found file with full path --- vst/SfizzVstProcessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vst/SfizzVstProcessor.cpp b/vst/SfizzVstProcessor.cpp index 708979eb..674e27b8 100644 --- a/vst/SfizzVstProcessor.cpp +++ b/vst/SfizzVstProcessor.cpp @@ -132,7 +132,7 @@ tresult PLUGIN_API SfizzVstProcessor::setState(IBStream* stream) if (!fileScan.locateRealFile(pathOrig, pathFound)) fprintf(stderr, "[Sfizz] file not found: %s\n", pathOrig.filename().u8string().c_str()); else { - fprintf(stderr, "[Sfizz] file found: %s\n", pathFound.filename().u8string().c_str()); + fprintf(stderr, "[Sfizz] file found: %s\n", pathFound.u8string().c_str()); *statePath = pathFound.u8string(); } }