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) {} | |||