From b088240281ec43dcdce92426b85d09a11de7a606 Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 25 Jun 2020 19:04:56 +0100 Subject: [PATCH] carla-lv2: First attempt at getting project dir from host Signed-off-by: falkTX --- source/plugin/carla-lv2.cpp | 69 ++++++++++++++++++++++++++++++++-- source/utils/CarlaLv2Utils.hpp | 8 +++- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/source/plugin/carla-lv2.cpp b/source/plugin/carla-lv2.cpp index a5f3a7551..a58d1e19a 100644 --- a/source/plugin/carla-lv2.cpp +++ b/source/plugin/carla-lv2.cpp @@ -41,6 +41,8 @@ #include "water/files/File.h" +static const char* const kPathForCarlaFiles = "carlafiles"; + template<> void Lv2PluginBaseClass::clearTimeData() noexcept { @@ -72,6 +74,7 @@ public: #if defined(USING_JUCE) && (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) fJuceInitialiser(), #endif + fLastProjectPath(nullptr), fLoadedFile(), fWorkerUISignal(0) { @@ -104,6 +107,12 @@ public: fHost.ui_open_file = host_ui_open_file; fHost.ui_save_file = host_ui_save_file; fHost.dispatcher = host_dispatcher; + +#if 0 + // NOTE: a few hosts crash with this :( + if (fMakePath != nullptr && fMakePath->path != nullptr) + fLastProjectPath = fMakePath->path(fMakePath->handle, kPathForCarlaFiles); +#endif } ~NativePlugin() @@ -121,6 +130,12 @@ public: delete[] fHost.uiName; fHost.uiName = nullptr; } + + if (fLastProjectPath != nullptr) + { + std::free(fLastProjectPath); + fLastProjectPath = nullptr; + } } // ---------------------------------------------------------------------------------------------------------------- @@ -410,9 +425,45 @@ public: // ---------------------------------------------------------------------------------------------------------------- + void saveLastProjectPathIfPossible(const LV2_Feature* const* const features) + { + char* const last = fLastProjectPath; + + if (fMakePath != nullptr && fMakePath->path != nullptr) + { + fLastProjectPath = fMakePath->path(fMakePath->handle, kPathForCarlaFiles); + } + else if (features != nullptr) + { + const LV2_State_Make_Path* makePath = nullptr; + + for (int i=0; features[i] != nullptr; ++i) + { + if (std::strcmp(features[i]->URI, LV2_STATE__makePath) == 0) + { + makePath = (const LV2_State_Make_Path*)features[i]->data; + break; + } + } + + if (makePath != nullptr && makePath->path != nullptr) + fLastProjectPath = makePath->path(makePath->handle, kPathForCarlaFiles); + else + fLastProjectPath = nullptr; + } + else + { + fLastProjectPath = nullptr; + } + + std::free(last); + } + LV2_State_Status lv2_save(const LV2_State_Store_Function store, const LV2_State_Handle handle, - const uint32_t /*flags*/, const LV2_Feature* const* const /*features*/) const + const uint32_t /*flags*/, const LV2_Feature* const* const features) { + saveLastProjectPathIfPossible(features); + if (fDescriptor->hints & NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE) { store(handle, @@ -429,7 +480,8 @@ public: if (char* const state = fDescriptor->get_state(fHandle)) { - store(handle, fUridMap->map(fUridMap->handle, "http://kxstudio.sf.net/ns/carla/chunk"), state, std::strlen(state)+1, fURIs.atomString, LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE); + store(handle, fUridMap->map(fUridMap->handle, "http://kxstudio.sf.net/ns/carla/chunk"), + state, std::strlen(state)+1, fURIs.atomString, LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE); std::free(state); return LV2_STATE_SUCCESS; } @@ -438,8 +490,10 @@ public: } LV2_State_Status lv2_restore(const LV2_State_Retrieve_Function retrieve, const LV2_State_Handle handle, - uint32_t flags, const LV2_Feature* const* const /*features*/) + uint32_t flags, const LV2_Feature* const* const features) { + saveLastProjectPathIfPossible(features); + size_t size = 0; uint32_t type = 0; @@ -804,10 +858,15 @@ protected: case NATIVE_HOST_OPCODE_INTERNAL_PLUGIN: case NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY: case NATIVE_HOST_OPCODE_REQUEST_IDLE: - case NATIVE_HOST_OPCODE_GET_FILE_PATH: // nothing break; + case NATIVE_HOST_OPCODE_GET_FILE_PATH: + CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0); + if (fLastProjectPath != nullptr) + return static_cast((uintptr_t)fLastProjectPath); + break; + case NATIVE_HOST_OPCODE_UI_UNAVAILABLE: handleUiClosed(); break; @@ -868,7 +927,9 @@ private: juce::SharedResourcePointer fJuceInitialiser; #endif + char* fLastProjectPath; CarlaString fLoadedFile; + int fWorkerUISignal; // ------------------------------------------------------------------- diff --git a/source/utils/CarlaLv2Utils.hpp b/source/utils/CarlaLv2Utils.hpp index 3a837e06b..e37942583 100644 --- a/source/utils/CarlaLv2Utils.hpp +++ b/source/utils/CarlaLv2Utils.hpp @@ -570,6 +570,7 @@ public: fUsingNominal(false), fBufferSize(0), fSampleRate(sampleRate), + fMakePath(nullptr), fUridMap(nullptr), fUridUnmap(nullptr), fWorker(nullptr), @@ -589,6 +590,7 @@ public: return; } + const LV2_State_Make_Path* makePath = nullptr; const LV2_Options_Option* options = nullptr; const LV2_URID_Map* uridMap = nullptr; const LV2_URID_Unmap* uridUnmap = nullptr; @@ -596,7 +598,9 @@ public: for (int i=0; features[i] != nullptr; ++i) { - /**/ if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0) + /**/ if (std::strcmp(features[i]->URI, LV2_STATE__makePath) == 0) + makePath = (const LV2_State_Make_Path*)features[i]->data; + else if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0) options = (const LV2_Options_Option*)features[i]->data; else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0) uridMap = (const LV2_URID_Map*)features[i]->data; @@ -663,6 +667,7 @@ public: fUridMap = uridMap; fURIs.map(uridMap); + fMakePath = makePath; fUridUnmap = uridUnmap; fWorker = worker; @@ -1178,6 +1183,7 @@ protected: double fSampleRate; // LV2 host features + const LV2_State_Make_Path* fMakePath; const LV2_URID_Map* fUridMap; const LV2_URID_Unmap* fUridUnmap; const LV2_Worker_Schedule* fWorker;