Signed-off-by: falkTX <falktx@falktx.com>tags/v2.1-rc1
| @@ -862,7 +862,7 @@ public: | |||
| * Returned variable must be deleted if non-null. | |||
| * @see ENGINE_CALLBACK_PLUGIN_RENAMED | |||
| */ | |||
| virtual const char* renamePlugin(const uint id, const char* const newName); | |||
| virtual bool renamePlugin(const uint id, const char* const newName); | |||
| /*! | |||
| * Clone plugin with id @a id. | |||
| @@ -880,6 +880,15 @@ public: | |||
| * Switch plugins with id @a idA and @a idB. | |||
| */ | |||
| bool switchPlugins(const uint idA, const uint idB) noexcept; | |||
| /*! | |||
| * Set a plugin's parameter in drag/touch mode. | |||
| * Usually happens from a UI when the user is moving a parameter with a mouse or similar input. | |||
| * | |||
| * @param parameterId The parameter to update | |||
| * @param touch The new state for the parameter | |||
| */ | |||
| virtual void touchPluginParameter(const uint id, const uint32_t parameterId, const bool touch) noexcept; | |||
| #endif | |||
| /*! | |||
| @@ -542,7 +542,7 @@ CARLA_EXPORT bool carla_remove_all_plugins(); | |||
| * @param pluginId Plugin to rename | |||
| * @param newName New plugin name | |||
| */ | |||
| CARLA_EXPORT const char* carla_rename_plugin(uint pluginId, const char* newName); | |||
| CARLA_EXPORT bool carla_rename_plugin(uint pluginId, const char* newName); | |||
| /*! | |||
| * Clone a plugin. | |||
| @@ -879,6 +879,15 @@ CARLA_EXPORT void carla_set_parameter_midi_channel(uint pluginId, uint32_t param | |||
| * @param cc New MIDI cc | |||
| */ | |||
| CARLA_EXPORT void carla_set_parameter_midi_cc(uint pluginId, uint32_t parameterId, int16_t cc); | |||
| /*! | |||
| * Change a plugin's parameter in drag/touch mode state. | |||
| * Usually happens from a UI when the user is moving a parameter with a mouse or similar input. | |||
| * @param pluginId Plugin | |||
| * @param parameterId Parameter index | |||
| * @param touch New state | |||
| */ | |||
| CARLA_EXPORT void carla_set_parameter_touch(uint pluginId, uint32_t parameterId, bool touch); | |||
| #endif | |||
| /*! | |||
| @@ -954,10 +954,10 @@ bool carla_remove_all_plugins() | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| const char* carla_rename_plugin(uint pluginId, const char* newName) | |||
| bool carla_rename_plugin(uint pluginId, const char* newName) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0', nullptr); | |||
| CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", nullptr); | |||
| CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0', false); | |||
| CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(gStandalone.engine != nullptr, "Engine is not initialized", false); | |||
| carla_debug("carla_rename_plugin(%i, \"%s\")", pluginId, newName); | |||
| @@ -1812,6 +1812,14 @@ void carla_set_parameter_midi_cc(uint pluginId, uint32_t parameterId, int16_t cc | |||
| return plugin->setParameterMidiCC(parameterId, cc, true, false); | |||
| } | |||
| void carla_set_parameter_touch(uint pluginId, uint32_t parameterId, bool touch) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); | |||
| carla_debug("carla_set_parameter_touch(%i, %i, %s)", pluginId, parameterId, bool2str(touch)); | |||
| return gStandalone.engine->touchPluginParameter(pluginId, parameterId, touch); | |||
| } | |||
| #endif | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -752,30 +752,32 @@ bool CarlaEngine::removeAllPlugins() | |||
| } | |||
| #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
| const char* CarlaEngine::renamePlugin(const uint id, const char* const newName) | |||
| bool CarlaEngine::renamePlugin(const uint id, const char* const newName) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN_ERRN(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERRN(pData->plugins != nullptr, "Invalid engine internal data"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERRN(pData->curPluginCount != 0, "Invalid engine internal data"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERRN(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERRN(id < pData->curPluginCount, "Invalid plugin Id"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERRN(newName != nullptr && newName[0] != '\0', "Invalid plugin name"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(newName != nullptr && newName[0] != '\0', "Invalid plugin name"); | |||
| carla_debug("CarlaEngine::renamePlugin(%i, \"%s\")", id, newName); | |||
| CarlaPlugin* const plugin(pData->plugins[id].plugin); | |||
| CARLA_SAFE_ASSERT_RETURN_ERRN(plugin != nullptr, "Could not find plugin to rename"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERRN(plugin->getId() == id, "Invalid engine internal data"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to rename"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data"); | |||
| const char* const uniqueName(getUniquePluginName(newName)); | |||
| CARLA_SAFE_ASSERT_RETURN_ERRN(uniqueName != nullptr, "Unable to get new unique plugin name"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(uniqueName != nullptr, "Unable to get new unique plugin name"); | |||
| plugin->setName(uniqueName); | |||
| if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
| pData->graph.renamePlugin(plugin, uniqueName); | |||
| callback(true, true, ENGINE_CALLBACK_PLUGIN_RENAMED, id, 0, 0, 0, 0.0f, uniqueName); | |||
| delete[] uniqueName; | |||
| return plugin->getName(); | |||
| return true; | |||
| } | |||
| bool CarlaEngine::clonePlugin(const uint id) | |||
| @@ -875,6 +877,10 @@ bool CarlaEngine::switchPlugins(const uint idA, const uint idB) noexcept | |||
| return true; | |||
| } | |||
| void CarlaEngine::touchPluginParameter(const uint, const uint32_t, const bool) noexcept | |||
| { | |||
| } | |||
| #endif | |||
| CarlaPlugin* CarlaEngine::getPlugin(const uint id) const noexcept | |||
| @@ -1357,7 +1357,7 @@ public: | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| const char* renamePlugin(const uint id, const char* const newName) override | |||
| bool renamePlugin(const uint id, const char* const newName) override | |||
| { | |||
| if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || | |||
| pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
| @@ -1365,14 +1365,14 @@ public: | |||
| return CarlaEngine::renamePlugin(id, newName); | |||
| } | |||
| CARLA_SAFE_ASSERT_RETURN(pData->plugins != nullptr, nullptr); | |||
| CARLA_SAFE_ASSERT_RETURN(pData->curPluginCount != 0, nullptr); | |||
| CARLA_SAFE_ASSERT_RETURN(id < pData->curPluginCount, nullptr); | |||
| CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0', nullptr); | |||
| CARLA_SAFE_ASSERT_RETURN(pData->plugins != nullptr, false); | |||
| CARLA_SAFE_ASSERT_RETURN(pData->curPluginCount != 0, false); | |||
| CARLA_SAFE_ASSERT_RETURN(id < pData->curPluginCount, false); | |||
| CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0', false); | |||
| CarlaPlugin* const plugin(pData->plugins[id].plugin); | |||
| CARLA_SAFE_ASSERT_RETURN_ERRN(plugin != nullptr, "Could not find plugin to rename"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERRN(plugin->getId() == id, "Invalid engine internal data"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to rename"); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data"); | |||
| // before we stop the engine thread we might need to get the plugin data | |||
| const bool needsReinit = (pData->options.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS); | |||
| @@ -1395,7 +1395,7 @@ public: | |||
| if (uniqueName.isEmpty()) | |||
| { | |||
| setLastError("Failed to request new unique plugin name"); | |||
| return nullptr; | |||
| return false; | |||
| } | |||
| const ScopedThreadStopper sts(this); | |||
| @@ -1408,7 +1408,7 @@ public: | |||
| if (! client->renameInSingleClient(uniqueName)) | |||
| { | |||
| setLastError("Failed to rename some JACK ports, does your JACK version support proper port renaming?"); | |||
| return nullptr; | |||
| return false; | |||
| } | |||
| } | |||
| // rename in multiple client mode | |||
| @@ -1493,7 +1493,7 @@ public: | |||
| else | |||
| { | |||
| setLastError("Failed to create new JACK client"); | |||
| return nullptr; | |||
| return false; | |||
| } | |||
| } | |||
| @@ -1508,7 +1508,7 @@ public: | |||
| plugin->setEnabled(true); | |||
| } | |||
| return plugin->getName(); | |||
| return true; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -331,15 +331,10 @@ public: | |||
| // ------------------------------------------------------------------- | |||
| const char* renamePlugin(const uint id, const char* const newName) override | |||
| void touchPluginParameter(const uint id, const uint32_t parameterId, const bool touch) noexcept override | |||
| { | |||
| if (const char* const retName = CarlaEngine::renamePlugin(id, newName)) | |||
| { | |||
| uiServerCallback(ENGINE_CALLBACK_PLUGIN_RENAMED, id, 0, 0, 0, 0.0f, retName); | |||
| return retName; | |||
| } | |||
| return nullptr; | |||
| carla_stdout("engineNative touchPluginParameter %u %u %s", id, parameterId, bool2str(touch)); | |||
| setParameterTouchFromUI(id, parameterId, touch); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -353,6 +348,15 @@ public: | |||
| pHost->ui_parameter_changed(pHost->handle, index, value); | |||
| } | |||
| void setParameterTouchFromUI(const uint32_t pluginId, const uint32_t index, const bool touch) | |||
| { | |||
| if (pluginId != 0) | |||
| return; | |||
| carla_stdout("engineNative setParameterTouchFromUI %u %u %s", pluginId,index, bool2str(touch)); | |||
| pHost->ui_parameter_touch(pHost->handle, index, touch); | |||
| } | |||
| void reloadFromUI() | |||
| { | |||
| carla_zeroFloats(fParameters, kNumInParams+kNumOutParams); | |||
| @@ -1927,8 +1931,7 @@ bool CarlaEngineNativeUI::msgReceived(const char*const msg) noexcept | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(newName), true); | |||
| // TODO | |||
| /*const char* name =*/ fEngine->renamePlugin(pluginId, newName); | |||
| ok = fEngine->renamePlugin(pluginId, newName); | |||
| delete[] newName; | |||
| } | |||
| @@ -2119,6 +2122,18 @@ bool CarlaEngineNativeUI::msgReceived(const char*const msg) noexcept | |||
| if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
| plugin->setParameterMidiCC(parameterId, static_cast<int16_t>(cc), true, false); | |||
| } | |||
| else if (std::strcmp(msg, "set_parameter_touch") == 0) | |||
| { | |||
| uint32_t pluginId, parameterId; | |||
| bool touching; | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(touching), true); | |||
| if (fEngine->getPlugin(pluginId) != nullptr) | |||
| fEngine->setParameterTouchFromUI(pluginId, parameterId, touching); | |||
| } | |||
| else if (std::strcmp(msg, "set_program") == 0) | |||
| { | |||
| uint32_t pluginId; | |||
| @@ -1159,8 +1159,19 @@ protected: | |||
| pData->engine->callback(true, true, ENGINE_CALLBACK_UPDATE, pData->id, 0, 0, 0, 0.0f, nullptr); | |||
| } | |||
| void audioProcessorParameterChangeGestureBegin(juce::AudioProcessor*, int) override {} | |||
| void audioProcessorParameterChangeGestureEnd(juce::AudioProcessor*, int) override {} | |||
| void audioProcessorParameterChangeGestureBegin(juce::AudioProcessor*, int index) override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index >= 0,); | |||
| pData->engine->touchPluginParameter(pData->id, static_cast<uint32_t>(index), true); | |||
| } | |||
| void audioProcessorParameterChangeGestureEnd(juce::AudioProcessor*, int index) override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index >= 0,); | |||
| pData->engine->touchPluginParameter(pData->id, static_cast<uint32_t>(index), false); | |||
| } | |||
| bool getCurrentPosition(CurrentPositionInfo& result) override | |||
| { | |||
| @@ -615,6 +615,9 @@ public: | |||
| if (fFeatures[kFeatureIdUiResize] != nullptr && fFeatures[kFeatureIdUiResize]->data != nullptr) | |||
| delete (LV2UI_Resize*)fFeatures[kFeatureIdUiResize]->data; | |||
| if (fFeatures[kFeatureIdUiTouch] != nullptr && fFeatures[kFeatureIdUiTouch]->data != nullptr) | |||
| delete (LV2UI_Touch*)fFeatures[kFeatureIdUiTouch]->data; | |||
| if (fFeatures[kFeatureIdExternalUi] != nullptr && fFeatures[kFeatureIdExternalUi]->data != nullptr) | |||
| delete (LV2_External_UI_Host*)fFeatures[kFeatureIdExternalUi]->data; | |||
| @@ -5109,6 +5112,25 @@ public: | |||
| return 0; | |||
| } | |||
| void handleUITouch(const uint32_t rindex, const bool touch) | |||
| { | |||
| carla_stdout("CarlaPluginLV2::handleUITouch(%u, %s)", rindex, bool2str(touch)); | |||
| uint32_t index = LV2UI_INVALID_PORT_INDEX; | |||
| for (uint32_t i=0; i < pData->param.count; ++i) | |||
| { | |||
| if (pData->param.data[i].rindex != static_cast<int32_t>(rindex)) | |||
| continue; | |||
| index = i; | |||
| break; | |||
| } | |||
| CARLA_SAFE_ASSERT_RETURN(index != LV2UI_INVALID_PORT_INDEX,); | |||
| pData->engine->touchPluginParameter(pData->id, index, touch); | |||
| } | |||
| void handleUIWrite(const uint32_t rindex, const uint32_t bufferSize, const uint32_t format, const void* const buffer) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,); | |||
| @@ -6048,6 +6070,10 @@ public: | |||
| uiResizeFt->handle = this; | |||
| uiResizeFt->ui_resize = carla_lv2_ui_resize; | |||
| LV2UI_Touch* const uiTouchFt = new LV2UI_Touch; | |||
| uiTouchFt->handle = this; | |||
| uiTouchFt->touch = carla_lv2_ui_touch; | |||
| LV2_External_UI_Host* const uiExternalHostFt = new LV2_External_UI_Host; | |||
| uiExternalHostFt->ui_closed = carla_lv2_external_ui_closed; | |||
| uiExternalHostFt->plugin_human_id = fLv2Options.windowTitle; | |||
| @@ -6092,7 +6118,7 @@ public: | |||
| fFeatures[kFeatureIdUiResize]->data = uiResizeFt; | |||
| fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch; | |||
| fFeatures[kFeatureIdUiTouch]->data = nullptr; | |||
| fFeatures[kFeatureIdUiTouch]->data = uiTouchFt; | |||
| fFeatures[kFeatureIdExternalUi]->URI = LV2_EXTERNAL_UI__Host; | |||
| fFeatures[kFeatureIdExternalUi]->data = uiExternalHostFt; | |||
| @@ -6770,6 +6796,17 @@ private: | |||
| return ((CarlaPluginLV2*)handle)->handleUIResize(width, height); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // UI Touch Feature | |||
| static void carla_lv2_ui_touch(LV2UI_Feature_Handle handle, uint32_t port_index, bool touch) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(handle != nullptr,); | |||
| carla_debug("carla_lv2_ui_touch(%p, %u, %s)", handle, port_index, bool2str(touch)); | |||
| ((CarlaPluginLV2*)handle)->handleUITouch(port_index, touch); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // UI Extension | |||
| @@ -279,6 +279,7 @@ public: | |||
| fHost.get_time_info = carla_host_get_time_info; | |||
| fHost.write_midi_event = carla_host_write_midi_event; | |||
| fHost.ui_parameter_changed = carla_host_ui_parameter_changed; | |||
| fHost.ui_parameter_touch = carla_host_ui_parameter_touch; | |||
| fHost.ui_custom_data_changed = carla_host_ui_custom_data_changed; | |||
| fHost.ui_closed = carla_host_ui_closed; | |||
| fHost.ui_open_file = carla_host_ui_open_file; | |||
| @@ -2393,6 +2394,12 @@ protected: | |||
| setParameterValue(index, value, false, true, true); | |||
| } | |||
| void handleUiParameterTouch(const uint32_t index, const bool touch) const | |||
| { | |||
| carla_stdout("pluginNative handleUiParameterTouch %u %s", index, bool2str(touch)); | |||
| pData->engine->touchPluginParameter(pData->id, index, touch); | |||
| } | |||
| void handleUiCustomDataChanged(const char* const key, const char* const value) | |||
| { | |||
| setCustomData(CUSTOM_DATA_TYPE_STRING, key, value, false); | |||
| @@ -2696,6 +2703,11 @@ private: | |||
| handlePtr->handleUiParameterChanged(index, value); | |||
| } | |||
| static void carla_host_ui_parameter_touch(NativeHostHandle handle, uint32_t index, bool touch) | |||
| { | |||
| handlePtr->handleUiParameterTouch(index, touch); | |||
| } | |||
| static void carla_host_ui_custom_data_changed(NativeHostHandle handle, const char* key, const char* value) | |||
| { | |||
| handlePtr->handleUiCustomDataChanged(key, value); | |||
| @@ -2197,8 +2197,15 @@ protected: | |||
| break; | |||
| case audioMasterBeginEdit: | |||
| CARLA_SAFE_ASSERT_BREAK(index > 0); | |||
| carla_stdout("audioMasterBeginEdit %i", index); | |||
| pData->engine->touchPluginParameter(pData->id, static_cast<uint32_t>(index), true); | |||
| break; | |||
| case audioMasterEndEdit: | |||
| // TODO | |||
| CARLA_SAFE_ASSERT_BREAK(index > 0); | |||
| carla_stdout("audioMasterEndEdit %i", index); | |||
| pData->engine->touchPluginParameter(pData->id, static_cast<uint32_t>(index), false); | |||
| break; | |||
| case audioMasterOpenFileSelector: | |||
| @@ -1904,6 +1904,15 @@ class CarlaHostMeta(object): | |||
| def set_parameter_midi_cc(self, pluginId, parameterId, cc): | |||
| raise NotImplementedError | |||
| # Change a plugin's parameter in drag/touch mode state. | |||
| # Usually happens from a UI when the user is moving a parameter with a mouse or similar input. | |||
| # @param pluginId Plugin | |||
| # @param parameterId Parameter index | |||
| # @param touch New state | |||
| @abstractmethod | |||
| def set_parameter_touch(self, pluginId, parameterId, touch): | |||
| raise NotImplementedError | |||
| # Change a plugin's current program. | |||
| # @param pluginId Plugin | |||
| # @param programId New program | |||
| @@ -2133,7 +2142,7 @@ class CarlaHostNull(CarlaHostMeta): | |||
| return False | |||
| def rename_plugin(self, pluginId, newName): | |||
| return "" | |||
| return False | |||
| def clone_plugin(self, pluginId): | |||
| return False | |||
| @@ -2270,6 +2279,9 @@ class CarlaHostNull(CarlaHostMeta): | |||
| def set_parameter_midi_cc(self, pluginId, parameterId, cc): | |||
| return | |||
| def set_parameter_touch(self, pluginId, parameterId, touch): | |||
| return | |||
| def set_program(self, pluginId, programId): | |||
| return | |||
| @@ -2430,7 +2442,7 @@ class CarlaHostDLL(CarlaHostMeta): | |||
| self.lib.carla_remove_all_plugins.restype = c_bool | |||
| self.lib.carla_rename_plugin.argtypes = [c_uint, c_char_p] | |||
| self.lib.carla_rename_plugin.restype = c_char_p | |||
| self.lib.carla_rename_plugin.restype = c_bool | |||
| self.lib.carla_clone_plugin.argtypes = [c_uint] | |||
| self.lib.carla_clone_plugin.restype = c_bool | |||
| @@ -2567,6 +2579,9 @@ class CarlaHostDLL(CarlaHostMeta): | |||
| self.lib.carla_set_parameter_midi_cc.argtypes = [c_uint, c_uint32, c_int16] | |||
| self.lib.carla_set_parameter_midi_cc.restype = None | |||
| self.lib.carla_set_parameter_touch.argtypes = [c_uint, c_uint32, c_bool] | |||
| self.lib.carla_set_parameter_touch.restype = None | |||
| self.lib.carla_set_program.argtypes = [c_uint, c_uint32] | |||
| self.lib.carla_set_program.restype = None | |||
| @@ -2722,7 +2737,7 @@ class CarlaHostDLL(CarlaHostMeta): | |||
| return bool(self.lib.carla_remove_all_plugins()) | |||
| def rename_plugin(self, pluginId, newName): | |||
| return charPtrToString(self.lib.carla_rename_plugin(pluginId, newName.encode("utf-8"))) | |||
| return bool(self.lib.carla_rename_plugin(pluginId, newName.encode("utf-8"))) | |||
| def clone_plugin(self, pluginId): | |||
| return bool(self.lib.carla_clone_plugin(pluginId)) | |||
| @@ -2872,6 +2887,9 @@ class CarlaHostDLL(CarlaHostMeta): | |||
| def set_parameter_midi_cc(self, pluginId, parameterId, cc): | |||
| self.lib.carla_set_parameter_midi_cc(pluginId, parameterId, cc) | |||
| def set_parameter_touch(self, pluginId, parameterId, touch): | |||
| self.lib.carla_set_parameter_touch(pluginId, parameterId, touch) | |||
| def set_program(self, pluginId, programId): | |||
| self.lib.carla_set_program(pluginId, programId) | |||
| @@ -3097,11 +3115,7 @@ class CarlaHostPlugin(CarlaHostMeta): | |||
| return self.sendMsgAndSetError(["remove_all_plugins"]) | |||
| def rename_plugin(self, pluginId, newName): | |||
| if self.sendMsg(["rename_plugin", pluginId, newName]): | |||
| return newName | |||
| self.fLastError = "Communication error with backend" | |||
| return "" | |||
| return self.sendMsgAndSetError(["rename_plugin", pluginId, newName]) | |||
| def clone_plugin(self, pluginId): | |||
| return self.sendMsgAndSetError(["clone_plugin", pluginId]) | |||
| @@ -3263,6 +3277,9 @@ class CarlaHostPlugin(CarlaHostMeta): | |||
| self.sendMsg(["set_parameter_midi_cc", pluginId, parameterId, cc]) | |||
| self.fPluginsInfo[pluginId].parameterData[parameterId]['midiCC'] = cc | |||
| def set_parameter_touch(self, pluginId, parameterId, touch): | |||
| self.sendMsg(["set_parameter_touch", pluginId, parameterId, touch]) | |||
| def set_program(self, pluginId, programId): | |||
| self.sendMsg(["set_program", pluginId, programId]) | |||
| self.fPluginsInfo[pluginId].programCurrent = programId | |||
| @@ -624,6 +624,7 @@ class AbstractPluginSlot(QFrame, PluginEditParentMeta): | |||
| for paramIndex, paramWidget in self.fParameterList: | |||
| paramWidget.setContextMenuPolicy(Qt.CustomContextMenu) | |||
| paramWidget.customContextMenuRequested.connect(self.slot_knobCustomMenu) | |||
| paramWidget.dragStateChanged.connect(self.slot_parameterDragStateChanged) | |||
| paramWidget.realValueChanged.connect(self.slot_parameterValueChanged) | |||
| paramWidget.blockSignals(True) | |||
| paramWidget.setValue(self.host.get_internal_parameter_value(self.fPluginId, paramIndex)) | |||
| @@ -797,8 +798,6 @@ class AbstractPluginSlot(QFrame, PluginEditParentMeta): | |||
| self.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) | |||
| return | |||
| self.setName(newName) | |||
| def showReplaceDialog(self): | |||
| data = gCarla.gui.showAddPluginDialog() | |||
| @@ -1360,6 +1359,13 @@ class AbstractPluginSlot(QFrame, PluginEditParentMeta): | |||
| #------------------------------------------------------------------ | |||
| @pyqtSlot(bool) | |||
| def slot_parameterDragStateChanged(self, touch): | |||
| index = self.sender().getIndex() | |||
| if index >= 0: | |||
| self.host.set_parameter_touch(self.fPluginId, index, touch) | |||
| @pyqtSlot(float) | |||
| def slot_parameterValueChanged(self, value): | |||
| index = self.sender().getIndex() | |||
| @@ -293,6 +293,7 @@ class PluginParameter(QWidget): | |||
| self.ui.sb_channel.customContextMenuRequested.connect(self.slot_channelSpinboxCustomMenu) | |||
| self.ui.sb_control.valueChanged.connect(self.slot_controlSpinboxChanged) | |||
| self.ui.sb_channel.valueChanged.connect(self.slot_channelSpinboxChanged) | |||
| self.ui.widget.dragStateChanged.connect(self.slot_parameterDragStateChanged) | |||
| # ------------------------------------------------------------- | |||
| @@ -383,6 +384,10 @@ class PluginParameter(QWidget): | |||
| self.fMidiChannel = channel | |||
| self.midiChannelChanged.emit(self.fParameterId, channel) | |||
| @pyqtSlot(bool) | |||
| def slot_parameterDragStateChanged(self, touch): | |||
| self.host.set_parameter_touch(self.fPluginId, self.fParameterId, touch) | |||
| def _textCallBack(self): | |||
| return self.host.get_parameter_text(self.fPluginId, self.fParameterId) | |||
| @@ -107,6 +107,7 @@ class CustomInputDialog(QDialog): | |||
| class ParamProgressBar(QProgressBar): | |||
| # signals | |||
| dragStateChanged = pyqtSignal(bool) | |||
| valueChanged = pyqtSignal(float) | |||
| def __init__(self, parent): | |||
| @@ -217,6 +218,7 @@ class ParamProgressBar(QProgressBar): | |||
| if event.button() == Qt.LeftButton: | |||
| self.handleMouseEventPos(event.pos()) | |||
| self.fLeftClickDown = True | |||
| self.dragStateChanged.emit(True) | |||
| else: | |||
| self.fLeftClickDown = False | |||
| @@ -236,6 +238,7 @@ class ParamProgressBar(QProgressBar): | |||
| return | |||
| self.fLeftClickDown = False | |||
| self.dragStateChanged.emit(False) | |||
| QProgressBar.mouseReleaseEvent(self, event) | |||
| def paintEvent(self, event): | |||
| @@ -293,6 +296,8 @@ class ParamSpinBox(QAbstractSpinBox): | |||
| self.customContextMenuRequested.connect(self.slot_showCustomMenu) | |||
| self.fBar.valueChanged.connect(self.slot_progressBarValueChanged) | |||
| self.dragStateChanged = self.fBar.dragStateChanged | |||
| QTimer.singleShot(0, self.slot_updateProgressBarGeometry) | |||
| def setDefault(self, value): | |||
| @@ -52,6 +52,7 @@ class PixmapDial(QDial): | |||
| MODE_LINEAR = 1 | |||
| # signals | |||
| dragStateChanged = pyqtSignal(bool) | |||
| realValueChanged = pyqtSignal(float) | |||
| def __init__(self, parent, index=0): | |||
| @@ -305,6 +306,7 @@ class PixmapDial(QDial): | |||
| self.fIsPressed = True | |||
| self.fLastDragPos = event.pos() | |||
| self.fLastDragValue = self.fRealValue | |||
| self.dragStateChanged.emit(True) | |||
| def mouseMoveEvent(self, event): | |||
| if self.fDialMode == self.MODE_DEFAULT: | |||
| @@ -334,6 +336,7 @@ class PixmapDial(QDial): | |||
| if self.fIsPressed: | |||
| self.fIsPressed = False | |||
| self.dragStateChanged.emit(False) | |||
| def paintEvent(self, event): | |||
| painter = QPainter(self) | |||
| @@ -192,6 +192,7 @@ typedef struct { | |||
| bool (*write_midi_event)(NativeHostHandle handle, const NativeMidiEvent* event); | |||
| void (*ui_parameter_changed)(NativeHostHandle handle, uint32_t index, float value); | |||
| void (*ui_parameter_touch)(NativeHostHandle handle, uint32_t index, bool touch); | |||
| void (*ui_midi_program_changed)(NativeHostHandle handle, uint8_t channel, uint32_t bank, uint32_t program); | |||
| void (*ui_custom_data_changed)(NativeHostHandle handle, const char* key, const char* value); | |||
| void (*ui_closed)(NativeHostHandle handle); | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Native Plugin API (C++) | |||
| * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -113,6 +113,13 @@ protected: | |||
| pHost->ui_parameter_changed(pHost->handle, index, value); | |||
| } | |||
| void uiParameterTouch(const uint32_t index, const bool touch) const | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,); | |||
| pHost->ui_parameter_touch(pHost->handle, index, touch); | |||
| } | |||
| void uiMidiProgramChanged(const uint8_t channel, const uint32_t bank, const uint32_t program) const | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,); | |||
| @@ -98,9 +98,9 @@ public: | |||
| // --------------------------------------------- | |||
| protected: | |||
| void handleEditParameter(const uint32_t, const bool) | |||
| void handleEditParameter(const uint32_t index, const bool touch) | |||
| { | |||
| // TODO | |||
| fHost->ui_parameter_touch(fHost->handle, rindex, touch); | |||
| } | |||
| void handleSetParameterValue(const uint32_t rindex, const float value) | |||
| @@ -198,6 +198,7 @@ static void writePluginFile(const NativePluginDescriptor* const pluginDesc) | |||
| hostDesc.get_time_info = nullptr; | |||
| hostDesc.write_midi_event = nullptr; | |||
| hostDesc.ui_parameter_changed = nullptr; | |||
| hostDesc.ui_parameter_touch = nullptr; | |||
| hostDesc.ui_midi_program_changed = nullptr; | |||
| hostDesc.ui_custom_data_changed = nullptr; | |||
| hostDesc.ui_closed = nullptr; | |||
| @@ -94,6 +94,7 @@ public: | |||
| fHost.get_time_info = host_get_time_info; | |||
| fHost.write_midi_event = host_write_midi_event; | |||
| fHost.ui_parameter_changed = host_ui_parameter_changed; | |||
| fHost.ui_parameter_touch = host_ui_parameter_touch; | |||
| fHost.ui_custom_data_changed = host_ui_custom_data_changed; | |||
| fHost.ui_closed = host_ui_closed; | |||
| fHost.ui_open_file = host_ui_open_file; | |||
| @@ -492,6 +493,11 @@ public: | |||
| fUI.host = (const LV2_External_UI_Host*)features[i]->data; | |||
| break; | |||
| } | |||
| if (std::strcmp(features[i]->URI, LV2_UI__touch) == 0) | |||
| { | |||
| fUI.touch = (const LV2UI_Touch*)features[i]->data; | |||
| break; | |||
| } | |||
| } | |||
| if (fUI.host != nullptr) | |||
| @@ -648,6 +654,12 @@ protected: | |||
| fUI.writeFunction(fUI.controller, index+fPorts.indexOffset, sizeof(float), 0, &value); | |||
| } | |||
| void handleUiParameterTouch(const uint32_t index, const bool touch) const | |||
| { | |||
| if (fUI.touch != nullptr && fUI.touch->touch != nullptr) | |||
| fUI.touch->touch(fUI.touch->handle, index+fPorts.indexOffset, touch); | |||
| } | |||
| void handleUiCustomDataChanged(const char* const key, const char* const value) const | |||
| { | |||
| carla_stdout("TODO: handleUiCustomDataChanged %s %s", key, value); | |||
| @@ -668,6 +680,7 @@ protected: | |||
| fUI.host->ui_closed(fUI.controller); | |||
| fUI.host = nullptr; | |||
| fUI.touch = nullptr; | |||
| fUI.writeFunction = nullptr; | |||
| fUI.controller = nullptr; | |||
| } | |||
| @@ -784,6 +797,11 @@ private: | |||
| handlePtr->handleUiParameterChanged(index, value); | |||
| } | |||
| static void host_ui_parameter_touch(NativeHostHandle handle, uint32_t index, bool touch) | |||
| { | |||
| handlePtr->handleUiParameterTouch(index, touch); | |||
| } | |||
| static void host_ui_custom_data_changed(NativeHostHandle handle, const char* key, const char* value) | |||
| { | |||
| handlePtr->handleUiCustomDataChanged(key, value); | |||
| @@ -81,6 +81,7 @@ int main() | |||
| nullptr, // write_midi_event | |||
| nullptr, // ui_parameter_changed | |||
| nullptr, // ui_parameter_touch | |||
| nullptr, // ui_midi_program_changed | |||
| nullptr, // ui_custom_data_changed | |||
| nullptr, // ui_closed | |||
| @@ -17,10 +17,8 @@ | |||
| #include "carla-vst.hpp" | |||
| #ifndef CARLA_OS_LINUX | |||
| # include "ui_launcher.cpp" | |||
| # include "ui_launcher_res.cpp" | |||
| #endif | |||
| #include "ui_launcher.cpp" | |||
| #include "ui_launcher_res.cpp" | |||
| #include <cstring> | |||
| @@ -131,14 +131,15 @@ public: | |||
| fHost.get_time_info = host_get_time_info; | |||
| fHost.write_midi_event = host_write_midi_event; | |||
| fHost.ui_parameter_changed = host_ui_parameter_changed; | |||
| fHost.ui_parameter_touch = host_ui_parameter_touch; | |||
| fHost.ui_custom_data_changed = host_ui_custom_data_changed; | |||
| fHost.ui_closed = host_ui_closed; | |||
| fHost.ui_open_file = host_ui_open_file; | |||
| fHost.ui_save_file = host_ui_save_file; | |||
| fHost.dispatcher = host_dispatcher; | |||
| fVstRect.top = 0; | |||
| fVstRect.left = 0; | |||
| fVstRect.top = 0; | |||
| fVstRect.left = 0; | |||
| if (kIsUsingUILauncher) | |||
| { | |||
| @@ -406,8 +407,12 @@ public: | |||
| case effEditOpen: | |||
| if (fDescriptor->ui_show != nullptr) | |||
| { | |||
| #ifdef HAVE_X11 | |||
| if (! kIsUsingUILauncher) | |||
| if (kIsUsingUILauncher) | |||
| { | |||
| destoryUILauncher(fUiLauncher); | |||
| fUiLauncher = createUILauncher((intptr_t)ptr, fDescriptor, fHandle); | |||
| } | |||
| else | |||
| { | |||
| char strBuf[0xff+1]; | |||
| std::snprintf(strBuf, 0xff, P_INTPTR, (intptr_t)ptr); | |||
| @@ -422,12 +427,6 @@ public: | |||
| // reset CARLA_PLUGIN_EMBED_WINID just in case | |||
| carla_setenv("CARLA_PLUGIN_EMBED_WINID", "0"); | |||
| } | |||
| else | |||
| #endif | |||
| { | |||
| destoryUILauncher(fUiLauncher); | |||
| fUiLauncher = createUILauncher((intptr_t)ptr, fDescriptor, fHandle); | |||
| } | |||
| ret = 1; | |||
| } | |||
| break; | |||
| @@ -435,16 +434,14 @@ public: | |||
| case effEditClose: | |||
| if (fDescriptor->ui_show != nullptr) | |||
| { | |||
| #ifdef HAVE_X11 | |||
| if (! kIsUsingUILauncher) | |||
| if (kIsUsingUILauncher) | |||
| { | |||
| fDescriptor->ui_show(fHandle, false); | |||
| destoryUILauncher(fUiLauncher); | |||
| fUiLauncher = nullptr; | |||
| } | |||
| else | |||
| #endif | |||
| { | |||
| destoryUILauncher(fUiLauncher); | |||
| fUiLauncher = nullptr; | |||
| fDescriptor->ui_show(fHandle, false); | |||
| } | |||
| ret = 1; | |||
| } | |||
| @@ -726,6 +723,12 @@ protected: | |||
| hostCallback(audioMasterAutomate, static_cast<int32_t>(index), 0, nullptr, normalizedValue); | |||
| } | |||
| void handleUiParameterTouch(const uint32_t index, const bool touch) const | |||
| { | |||
| carla_stdout("VST handleUiParameterTouch %u %s", index, bool2str(touch)); | |||
| hostCallback(touch ? audioMasterBeginEdit : audioMasterEndEdit, static_cast<int32_t>(index)); | |||
| } | |||
| void handleUiCustomDataChanged(const char* const /*key*/, const char* const /*value*/) const | |||
| { | |||
| } | |||
| @@ -877,6 +880,11 @@ private: | |||
| handlePtr->handleUiParameterChanged(index, value); | |||
| } | |||
| static void host_ui_parameter_touch(NativeHostHandle handle, uint32_t index, bool touch) | |||
| { | |||
| handlePtr->handleUiParameterTouch(index, touch); | |||
| } | |||
| static void host_ui_custom_data_changed(NativeHostHandle handle, const char* key, const char* value) | |||
| { | |||
| handlePtr->handleUiCustomDataChanged(key, value); | |||
| @@ -15,11 +15,14 @@ | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #ifndef CARLA_VST_HPP_INCLUDED | |||
| #define CARLA_VST_HPP_INCLUDED | |||
| #include "CarlaDefines.h" | |||
| #include "CarlaNative.h" | |||
| #include "vestige/vestige.h" | |||
| # include "ui_launcher_res.hpp" | |||
| #include "ui_launcher_res.hpp" | |||
| struct CarlaUILauncher; | |||
| class NativePlugin; | |||
| @@ -44,3 +47,5 @@ float vst_getParameterCallback(AEffect* effect, int32_t index); | |||
| void vst_setParameterCallback(AEffect* effect, int32_t index, float value); | |||
| void vst_processCallback(AEffect* effect, float** inputs, float** outputs, int32_t sampleFrames); | |||
| void vst_processReplacingCallback(AEffect* effect, float** inputs, float** outputs, int32_t sampleFrames); | |||
| #endif // CARLA_VST_HPP_INCLUDED | |||
| @@ -1137,6 +1137,7 @@ public: | |||
| handleUiHide(); | |||
| fUI.host = nullptr; | |||
| fUI.touch = nullptr; | |||
| fUI.writeFunction = nullptr; | |||
| fUI.controller = nullptr; | |||
| } | |||
| @@ -1535,12 +1536,14 @@ protected: | |||
| struct UI { | |||
| const LV2_External_UI_Host* host; | |||
| const LV2UI_Touch* touch; | |||
| LV2UI_Write_Function writeFunction; | |||
| LV2UI_Controller controller; | |||
| bool isVisible; | |||
| UI() | |||
| : host(nullptr), | |||
| touch(nullptr), | |||
| writeFunction(nullptr), | |||
| controller(nullptr), | |||
| isVisible(false) {} | |||