@@ -858,18 +858,26 @@ typedef enum { | |||
*/ | |||
ENGINE_CALLBACK_PATCHBAY_PORT_RENAMED = 25, | |||
/*! | |||
* A patchbay port value has changed. | |||
* @param pluginId Client Id | |||
* @param value1 Port Id | |||
* @param value3 New port value | |||
*/ | |||
ENGINE_CALLBACK_PATCHBAY_PORT_VALUE_CHANGED = 26, | |||
/*! | |||
* A patchbay connection has been added. | |||
* @param pluginId Connection Id | |||
* @param valueStr Out group, port plus in group and port, in "og:op:ig:ip" syntax. | |||
*/ | |||
ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED = 26, | |||
ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED = 27, | |||
/*! | |||
* A patchbay connection has been removed. | |||
* @param pluginId Connection Id | |||
*/ | |||
ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED = 27, | |||
ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED = 28, | |||
/*! | |||
* Engine started. | |||
@@ -879,62 +887,62 @@ typedef enum { | |||
* @see EngineProcessMode | |||
* @see EngineTransportMode | |||
*/ | |||
ENGINE_CALLBACK_ENGINE_STARTED = 28, | |||
ENGINE_CALLBACK_ENGINE_STARTED = 29, | |||
/*! | |||
* Engine stopped. | |||
*/ | |||
ENGINE_CALLBACK_ENGINE_STOPPED = 29, | |||
ENGINE_CALLBACK_ENGINE_STOPPED = 30, | |||
/*! | |||
* Engine process mode has changed. | |||
* @param value1 New process mode | |||
* @see EngineProcessMode | |||
*/ | |||
ENGINE_CALLBACK_PROCESS_MODE_CHANGED = 30, | |||
ENGINE_CALLBACK_PROCESS_MODE_CHANGED = 31, | |||
/*! | |||
* Engine transport mode has changed. | |||
* @param value1 New transport mode | |||
* @see EngineTransportMode | |||
*/ | |||
ENGINE_CALLBACK_TRANSPORT_MODE_CHANGED = 31, | |||
ENGINE_CALLBACK_TRANSPORT_MODE_CHANGED = 32, | |||
/*! | |||
* Engine buffer-size changed. | |||
* @param value1 New buffer size | |||
*/ | |||
ENGINE_CALLBACK_BUFFER_SIZE_CHANGED = 32, | |||
ENGINE_CALLBACK_BUFFER_SIZE_CHANGED = 33, | |||
/*! | |||
* Engine sample-rate changed. | |||
* @param value3 New sample rate | |||
*/ | |||
ENGINE_CALLBACK_SAMPLE_RATE_CHANGED = 33, | |||
ENGINE_CALLBACK_SAMPLE_RATE_CHANGED = 34, | |||
/*! | |||
* Idle frontend.\n | |||
* This is used by the engine during long operations that might block the frontend, | |||
* giving it the possibility to idle while the operation is still in place. | |||
*/ | |||
ENGINE_CALLBACK_IDLE = 34, | |||
ENGINE_CALLBACK_IDLE = 35, | |||
/*! | |||
* Show a message as information. | |||
* @param valueStr The message | |||
*/ | |||
ENGINE_CALLBACK_INFO = 35, | |||
ENGINE_CALLBACK_INFO = 36, | |||
/*! | |||
* Show a message as an error. | |||
* @param valueStr The message | |||
*/ | |||
ENGINE_CALLBACK_ERROR = 36, | |||
ENGINE_CALLBACK_ERROR = 37, | |||
/*! | |||
* The engine has crashed or malfunctioned and will no longer work. | |||
*/ | |||
ENGINE_CALLBACK_QUIT = 37 | |||
ENGINE_CALLBACK_QUIT = 38 | |||
} EngineCallbackOpcode; | |||
@@ -892,7 +892,7 @@ public: | |||
/*! | |||
* Connect patchbay ports \a portA and \a portB. | |||
*/ | |||
virtual bool patchbayConnect(const int portA, const int portB); | |||
virtual bool patchbayConnect(const int groupA, const int portA, const int groupB, const int portB); | |||
/*! | |||
* Disconnect patchbay connection \a connectionId. | |||
@@ -492,11 +492,13 @@ CARLA_EXPORT bool carla_save_project(const char* filename); | |||
#ifndef BUILD_BRIDGE | |||
/*! | |||
* Connect two patchbay ports. | |||
* @param portIdA Output port | |||
* @param portIdB Input port | |||
* @param groupIdA Output group | |||
* @param portIdA Output port | |||
* @param groupIdB Input group | |||
* @param portIdB Input port | |||
* @see ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED | |||
*/ | |||
CARLA_EXPORT bool carla_patchbay_connect(int portIdA, int portIdB); | |||
CARLA_EXPORT bool carla_patchbay_connect(int groupIdA, int portIdA, int groupIdB, int portIdB); | |||
/*! | |||
* Disconnect two patchbay ports. | |||
@@ -1663,7 +1663,7 @@ void CarlaEngine::setFileCallback(const FileCallbackFunc func, void* const ptr) | |||
// ----------------------------------------------------------------------- | |||
// Patchbay | |||
bool CarlaEngine::patchbayConnect(const int portA, const int portB) | |||
bool CarlaEngine::patchbayConnect(const int /*groupA*/, const int portA, const int /*groupB*/, const int portB) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY, false); | |||
CARLA_SAFE_ASSERT_RETURN(pData->bufAudio.isReady, false); | |||
@@ -2179,36 +2179,75 @@ void CarlaEngine::restorePatchbayConnection(const char* const connSource, const | |||
} | |||
else | |||
{ | |||
int sourcePort, targetPort; | |||
int sourceGroup, targetGroup; | |||
int sourcePort, targetPort; | |||
if (std::strncmp(connSource, "Carla:", 6) == 0) | |||
sourcePort = getCarlaPortIdFromName(connSource+6); | |||
{ | |||
sourceGroup = RACK_PATCHBAY_GROUP_CARLA; | |||
sourcePort = getCarlaPortIdFromName(connSource+6); | |||
} | |||
else if (std::strncmp(connSource, "AudioIn:", 8) == 0) | |||
sourcePort = std::atoi(connSource+8) + RACK_PATCHBAY_GROUP_AUDIO_IN*1000 - 1; | |||
{ | |||
sourceGroup = RACK_PATCHBAY_GROUP_AUDIO_IN; | |||
sourcePort = std::atoi(connSource+8) - 1; | |||
} | |||
else if (std::strncmp(connSource, "AudioOut:", 9) == 0) | |||
sourcePort = std::atoi(connSource+9) + RACK_PATCHBAY_GROUP_AUDIO_OUT*1000 - 1; | |||
{ | |||
sourceGroup = RACK_PATCHBAY_GROUP_AUDIO_OUT; | |||
sourcePort = std::atoi(connSource+9) - 1; | |||
} | |||
else if (std::strncmp(connSource, "MidiIn:", 7) == 0) | |||
sourcePort = std::atoi(connSource+7) + RACK_PATCHBAY_GROUP_MIDI_IN*1000 - 1; | |||
{ | |||
sourceGroup = RACK_PATCHBAY_GROUP_MIDI_IN; | |||
sourcePort = std::atoi(connSource+7) - 1; | |||
} | |||
else if (std::strncmp(connSource, "MidiOut:", 8) == 0) | |||
sourcePort = std::atoi(connSource+8) + RACK_PATCHBAY_GROUP_MIDI_OUT*1000 - 1; | |||
{ | |||
sourceGroup = RACK_PATCHBAY_GROUP_MIDI_OUT; | |||
sourcePort = std::atoi(connSource+8) - 1; | |||
} | |||
else | |||
sourcePort = RACK_PATCHBAY_PORT_MAX; | |||
{ | |||
sourceGroup = RACK_PATCHBAY_GROUP_MAX; | |||
sourcePort = RACK_PATCHBAY_PORT_MAX; | |||
} | |||
if (std::strncmp(connTarget, "Carla:", 6) == 0) | |||
targetPort = getCarlaPortIdFromName(connTarget+6); | |||
{ | |||
targetGroup = RACK_PATCHBAY_GROUP_CARLA; | |||
targetPort = getCarlaPortIdFromName(connTarget+6); | |||
} | |||
else if (std::strncmp(connTarget, "AudioIn:", 8) == 0) | |||
targetPort = std::atoi(connTarget+8) + RACK_PATCHBAY_GROUP_AUDIO_IN*1000 - 1; | |||
{ | |||
targetGroup = RACK_PATCHBAY_GROUP_AUDIO_IN; | |||
targetPort = std::atoi(connTarget+8) - 1; | |||
} | |||
else if (std::strncmp(connTarget, "AudioOut:", 9) == 0) | |||
targetPort = std::atoi(connTarget+9) + RACK_PATCHBAY_GROUP_AUDIO_OUT*1000 - 1; | |||
{ | |||
targetGroup = RACK_PATCHBAY_GROUP_AUDIO_OUT; | |||
targetPort = std::atoi(connTarget+9) - 1; | |||
} | |||
else if (std::strncmp(connTarget, "MidiIn:", 7) == 0) | |||
targetPort = std::atoi(connTarget+7) + RACK_PATCHBAY_GROUP_MIDI_IN*1000 - 1; | |||
{ | |||
targetGroup = RACK_PATCHBAY_GROUP_MIDI_IN; | |||
targetPort = std::atoi(connTarget+7) - 1; | |||
} | |||
else if (std::strncmp(connTarget, "MidiOut:", 8) == 0) | |||
targetPort = std::atoi(connTarget+8) + RACK_PATCHBAY_GROUP_MIDI_OUT*1000 - 1; | |||
{ | |||
targetGroup = RACK_PATCHBAY_GROUP_MIDI_OUT; | |||
targetPort = std::atoi(connTarget+8) - 1; | |||
} | |||
else | |||
targetPort = RACK_PATCHBAY_PORT_MAX; | |||
{ | |||
targetGroup = RACK_PATCHBAY_GROUP_MAX; | |||
targetPort = RACK_PATCHBAY_PORT_MAX; | |||
} | |||
CARLA_SAFE_ASSERT_RETURN(sourceGroup == RACK_PATCHBAY_GROUP_MAX || sourcePort == RACK_PATCHBAY_PORT_MAX,); | |||
CARLA_SAFE_ASSERT_RETURN(targetGroup == RACK_PATCHBAY_GROUP_MAX || targetPort == RACK_PATCHBAY_PORT_MAX,); | |||
if (sourcePort != RACK_PATCHBAY_PORT_MAX && targetPort != RACK_PATCHBAY_PORT_MAX) | |||
patchbayConnect(targetPort, sourcePort); | |||
patchbayConnect(targetGroup, targetPort, sourceGroup, sourcePort); | |||
} | |||
} | |||
#endif | |||
@@ -948,7 +948,7 @@ public: | |||
// ------------------------------------------------------------------- | |||
// Patchbay | |||
bool patchbayConnect(int portA, int portB) override | |||
bool patchbayConnect(const int groupA, const int portA, const int groupB, const int portB) override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, false); | |||
@@ -963,16 +963,14 @@ public: | |||
// both must be < 0 | |||
CARLA_SAFE_ASSERT_RETURN(portA < 0 && portB < 0, false); | |||
#if 0 | |||
ConnectionToId connectionToId; | |||
connectionToId.setData(fLastConnectionId++, portIdA.groupId, portIdA.portId, portIdB.groupId, portIdB.portId); | |||
connectionToId.setData(fLastConnectionId++, groupA, portA, groupB, portB); | |||
fUsedConnections.append(connectionToId); | |||
char strBuf[STR_MAX+1]; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", portIdA.groupId, portIdA.portId, portIdB.groupId, portIdB.portId); | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", groupA, portA, groupB, portB); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf); | |||
#endif | |||
return true; | |||
} | |||
@@ -991,7 +989,7 @@ public: | |||
return true; | |||
} | |||
bool patchbayDisconnect(uint connectionId) override | |||
bool patchbayDisconnect(const uint connectionId) override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, false); | |||
@@ -1949,6 +1947,7 @@ private: | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, static_cast<uint>(groupId), icon, pluginId, 0.0f, groupName); | |||
#if 0 | |||
if (pluginId >= 0) | |||
{ | |||
CarlaPlugin* const plugin(getPlugin(static_cast<uint32_t>(pluginId))); | |||
@@ -1970,10 +1969,15 @@ private: | |||
plugin->getParameterName(j, strBuf); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, static_cast<uint>(groupId), static_cast<int>(j)-1, static_cast<int>(canvasPortFlags), 0.0f, strBuf); | |||
const int pluginPortId = -static_cast<int>(j)-1; | |||
const float pluginValue = plugin->getParameterRanges(j).getNormalizedValue(plugin->getParameterValue(j)); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, static_cast<uint>(groupId), pluginPortId, static_cast<int>(canvasPortFlags), 0.0f, strBuf); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_VALUE_CHANGED, static_cast<uint>(groupId), pluginPortId, 0, pluginValue, nullptr); | |||
} | |||
} | |||
} | |||
#endif | |||
} | |||
bool portIsInput = (jackPortFlags & JackPortIsInput); | |||
@@ -113,12 +113,14 @@ protected: | |||
} | |||
else if (std::strcmp(msg, "patchbay_connect") == 0) | |||
{ | |||
int32_t portA, portB; | |||
int32_t groupA, portA, groupB, portB; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(groupA), true); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(portA), true); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(groupB), true); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(portB), true); | |||
ok = fEngine->patchbayConnect(portA, portB); | |||
ok = fEngine->patchbayConnect(groupA, portA, groupB, portB); | |||
} | |||
else if (std::strcmp(msg, "patchbay_disconnect") == 0) | |||
{ | |||
@@ -927,13 +927,12 @@ bool carla_save_project(const char* filename) | |||
#ifndef BUILD_BRIDGE | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
bool carla_patchbay_connect(int portIdA, int portIdB) | |||
bool carla_patchbay_connect(int groupIdA, int portIdA, int groupIdB, int portIdB) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(portIdA != portIdB, false); | |||
carla_debug("carla_patchbay_connect(%i, %i)", portIdA, portIdB); | |||
carla_debug("carla_patchbay_connect(%i, %i, %i, %i)", groupIdA, portIdA, groupIdB, portIdB); | |||
if (gStandalone.engine != nullptr) | |||
return gStandalone.engine->patchbayConnect(portIdA, portIdB); | |||
return gStandalone.engine->patchbayConnect(groupIdA, portIdA, groupIdB, portIdB); | |||
carla_stderr2("Engine is not running"); | |||
gStandalone.lastError = "Engine is not running"; | |||
@@ -80,6 +80,7 @@ class CarlaMultiW(QTabWidget): | |||
parent.ui.act_settings_configure.triggered.connect(self.fPatchbay.slot_configureCarla) | |||
parent.ParameterValueChangedCallback.connect(self.fRack.slot_handleParameterValueChangedCallback) | |||
parent.ParameterValueChangedCallback.connect(self.fPatchbay.slot_handleParameterValueChangedCallback) | |||
parent.ParameterDefaultChangedCallback.connect(self.fRack.slot_handleParameterDefaultChangedCallback) | |||
parent.ParameterMidiChannelChangedCallback.connect(self.fRack.slot_handleParameterMidiChannelChangedCallback) | |||
parent.ParameterMidiCcChangedCallback.connect(self.fRack.slot_handleParameterMidiCcChangedCallback) | |||
@@ -93,8 +94,10 @@ class CarlaMultiW(QTabWidget): | |||
parent.UpdateCallback.connect(self.fRack.slot_handleUpdateCallback) | |||
parent.ReloadInfoCallback.connect(self.fRack.slot_handleReloadInfoCallback) | |||
parent.ReloadParametersCallback.connect(self.fRack.slot_handleReloadParametersCallback) | |||
parent.ReloadParametersCallback.connect(self.fPatchbay.slot_handleReloadParametersCallback) | |||
parent.ReloadProgramsCallback.connect(self.fRack.slot_handleReloadProgramsCallback) | |||
parent.ReloadAllCallback.connect(self.fRack.slot_handleReloadAllCallback) | |||
parent.ReloadAllCallback.connect(self.fPatchbay.slot_handleReloadAllCallback) | |||
parent.PatchbayClientAddedCallback.connect(self.fPatchbay.slot_handlePatchbayClientAddedCallback) | |||
parent.PatchbayClientRemovedCallback.connect(self.fPatchbay.slot_handlePatchbayClientRemovedCallback) | |||
@@ -103,6 +106,7 @@ class CarlaMultiW(QTabWidget): | |||
parent.PatchbayPortAddedCallback.connect(self.fPatchbay.slot_handlePatchbayPortAddedCallback) | |||
parent.PatchbayPortRemovedCallback.connect(self.fPatchbay.slot_handlePatchbayPortRemovedCallback) | |||
parent.PatchbayPortRenamedCallback.connect(self.fPatchbay.slot_handlePatchbayPortRenamedCallback) | |||
parent.PatchbayPortValueChangedCallback.connect(self.fPatchbay.slot_handlePatchbayPortValueChangedCallback) | |||
parent.PatchbayConnectionAddedCallback.connect(self.fPatchbay.slot_handlePatchbayConnectionAddedCallback) | |||
parent.PatchbayConnectionRemovedCallback.connect(self.fPatchbay.slot_handlePatchbayConnectionRemovedCallback) | |||
@@ -154,6 +158,7 @@ class CarlaMultiW(QTabWidget): | |||
def idleSlow(self): | |||
self.fRack.idleSlow() | |||
self.fPatchbay.idleSlow() | |||
# ----------------------------------------------------------------- | |||
@@ -261,8 +261,8 @@ class PluginHost(object): | |||
# ------------------------------------------------------------------- | |||
def patchbay_connect(self, portIdA, portIdB): | |||
gCarla.gui.send(["patchbay_connect", portIdA, portIdB]) | |||
def patchbay_connect(self, groupIdA, portIdA, groupIdB, portIdB): | |||
gCarla.gui.send(["patchbay_connect", groupIdA, portIdA, groupIdB, portIdB]) | |||
return True | |||
def patchbay_disconnect(self, connectionId): | |||
@@ -648,14 +648,20 @@ ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED = 24 | |||
# @param valueStr New port name | |||
ENGINE_CALLBACK_PATCHBAY_PORT_RENAMED = 25 | |||
# A patchbay port value has changed. | |||
# @param pluginId Client Id | |||
# @param value1 Port Id | |||
# @param value3 New port value | |||
ENGINE_CALLBACK_PATCHBAY_PORT_VALUE_CHANGED = 26 | |||
# A patchbay connection has been added. | |||
# @param pluginId Connection Id | |||
# @param valueStr Out group, port plus in group and port, in "og:op:ig:ip" syntax. | |||
ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED = 26 | |||
ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED = 27 | |||
# A patchbay connection has been removed. | |||
# @param pluginId Connection Id | |||
ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED = 27 | |||
ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED = 28 | |||
# Engine started. | |||
# @param value1 Process mode | |||
@@ -663,44 +669,44 @@ ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED = 27 | |||
# @param valuestr Engine driver | |||
# @see EngineProcessMode | |||
# @see EngineTransportMode | |||
ENGINE_CALLBACK_ENGINE_STARTED = 28 | |||
ENGINE_CALLBACK_ENGINE_STARTED = 29 | |||
# Engine stopped. | |||
ENGINE_CALLBACK_ENGINE_STOPPED = 29 | |||
ENGINE_CALLBACK_ENGINE_STOPPED = 30 | |||
# Engine process mode has changed. | |||
# @param value1 New process mode | |||
# @see EngineProcessMode | |||
ENGINE_CALLBACK_PROCESS_MODE_CHANGED = 30 | |||
ENGINE_CALLBACK_PROCESS_MODE_CHANGED = 31 | |||
# Engine transport mode has changed. | |||
# @param value1 New transport mode | |||
# @see EngineTransportMode | |||
ENGINE_CALLBACK_TRANSPORT_MODE_CHANGED = 31 | |||
ENGINE_CALLBACK_TRANSPORT_MODE_CHANGED = 32 | |||
# Engine buffer-size changed. | |||
# @param value1 New buffer size | |||
ENGINE_CALLBACK_BUFFER_SIZE_CHANGED = 32 | |||
ENGINE_CALLBACK_BUFFER_SIZE_CHANGED = 33 | |||
# Engine sample-rate changed. | |||
# @param value3 New sample rate | |||
ENGINE_CALLBACK_SAMPLE_RATE_CHANGED = 33 | |||
ENGINE_CALLBACK_SAMPLE_RATE_CHANGED = 34 | |||
# Idle frontend. | |||
# This is used by the engine during long operations that might block the frontend, | |||
# giving it the possibility to idle while the operation is still in place. | |||
ENGINE_CALLBACK_IDLE = 34 | |||
ENGINE_CALLBACK_IDLE = 35 | |||
# Show a message as information. | |||
# @param valueStr The message | |||
ENGINE_CALLBACK_INFO = 35 | |||
ENGINE_CALLBACK_INFO = 36 | |||
# Show a message as an error. | |||
# @param valueStr The message | |||
ENGINE_CALLBACK_ERROR = 36 | |||
ENGINE_CALLBACK_ERROR = 37 | |||
# The engine has crashed or malfunctioned and will no longer work. | |||
ENGINE_CALLBACK_QUIT = 37 | |||
ENGINE_CALLBACK_QUIT = 38 | |||
# ------------------------------------------------------------------------------------------------------------ | |||
# Engine Option | |||
@@ -1345,11 +1351,13 @@ class Host(object): | |||
return bool(self.lib.carla_save_project(filename.encode("utf-8"))) | |||
# Connect two patchbay ports. | |||
# @param portIdA Output port | |||
# @param portIdB Input port | |||
# @param groupIdA Output group | |||
# @param portIdA Output port | |||
# @param groupIdB Input group | |||
# @param portIdB Input port | |||
# @see ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED | |||
def patchbay_connect(self, portIdA, portIdB): | |||
return bool(self.lib.carla_patchbay_connect(portIdA, portIdB)) | |||
def patchbay_connect(self, groupIdA, portIdA, groupIdB, portIdB): | |||
return bool(self.lib.carla_patchbay_connect(groupIdA, portIdA, groupIdB, portIdB)) | |||
# Disconnect two patchbay ports. | |||
# @param connectionId Connection Id | |||
@@ -1798,7 +1806,7 @@ class Host(object): | |||
self.lib.carla_save_project.argtypes = [c_char_p] | |||
self.lib.carla_save_project.restype = c_bool | |||
self.lib.carla_patchbay_connect.argtypes = [c_int, c_int] | |||
self.lib.carla_patchbay_connect.argtypes = [c_int, c_int, c_int, c_int] | |||
self.lib.carla_patchbay_connect.restype = c_bool | |||
self.lib.carla_patchbay_disconnect.argtypes = [c_uint] | |||
@@ -149,6 +149,7 @@ class HostWindow(QMainWindow): | |||
PatchbayPortAddedCallback = pyqtSignal(int, int, int, str) | |||
PatchbayPortRemovedCallback = pyqtSignal(int, int) | |||
PatchbayPortRenamedCallback = pyqtSignal(int, int, str) | |||
PatchbayPortValueChangedCallback = pyqtSignal(int, int, float) | |||
PatchbayConnectionAddedCallback = pyqtSignal(int, int, int, int, int) | |||
PatchbayConnectionRemovedCallback = pyqtSignal(int, int, int) | |||
EngineStartedCallback = pyqtSignal(int, int, str) | |||
@@ -741,7 +742,7 @@ class HostWindow(QMainWindow): | |||
if self.fIdleTimerSlow != 0: | |||
self.killTimer(self.fIdleTimerSlow) | |||
self.fIdleTimerSlow = self.startTimer(self.fSavedSettings[CARLA_KEY_MAIN_REFRESH_INTERVAL]*2) | |||
self.fIdleTimerSlow = self.startTimer(self.fSavedSettings[CARLA_KEY_MAIN_REFRESH_INTERVAL]*4) | |||
def saveSettings(self): | |||
settings = QSettings() | |||
@@ -1088,7 +1089,7 @@ class HostWindow(QMainWindow): | |||
if self.fIdleTimerFast == 0: | |||
self.fIdleTimerFast = self.startTimer(self.fSavedSettings[CARLA_KEY_MAIN_REFRESH_INTERVAL]) | |||
if self.fIdleTimerSlow == 0: | |||
self.fIdleTimerSlow = self.startTimer(self.fSavedSettings[CARLA_KEY_MAIN_REFRESH_INTERVAL]*2) | |||
self.fIdleTimerSlow = self.startTimer(self.fSavedSettings[CARLA_KEY_MAIN_REFRESH_INTERVAL]*4) | |||
@pyqtSlot() | |||
def slot_handleEngineStoppedCallback(self): | |||
@@ -1277,6 +1278,8 @@ def engineCallback(ptr, action, pluginId, value1, value2, value3, valueStr): | |||
gCarla.gui.PatchbayPortRemovedCallback.emit(pluginId, value1) | |||
elif action == ENGINE_CALLBACK_PATCHBAY_PORT_RENAMED: | |||
gCarla.gui.PatchbayPortRenamedCallback.emit(pluginId, value1, valueStr) | |||
elif action == ENGINE_CALLBACK_PATCHBAY_PORT_VALUE_CHANGED: | |||
gCarla.gui.PatchbayPortValueChangedCallback.emit(pluginId, value1, value3) | |||
elif action == ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED: | |||
gOut, pOut, gIn, pIn = [int(i) for i in valueStr.split(":")] | |||
gCarla.gui.PatchbayConnectionAddedCallback.emit(pluginId, gOut, pOut, gIn, pIn) | |||
@@ -60,6 +60,94 @@ except: | |||
CARLA_DEFAULT_CANVAS_SIZE_WIDTH = 3100 | |||
CARLA_DEFAULT_CANVAS_SIZE_HEIGHT = 2400 | |||
# ------------------------------------------------------------------------------------------------ | |||
# Patchbay info class, used in main carla as replacement for PluginEdit | |||
class PluginInfo(object): | |||
def __init__(self, parent, pluginId): | |||
object.__init__(self) | |||
self.fGroupId = None | |||
self.fPluginId = pluginId | |||
self.fParameterList = [] # type, index, min, max | |||
self.reloadParameters() | |||
def close(self): | |||
for paramType, paramIndex, paramMin, paramMax in self.fParameterList: | |||
patchcanvas.removePort(self.fGroupId, -paramIndex-1) | |||
#------------------------------------------------------------------ | |||
def reloadAll(self): | |||
self.reloadParameters() | |||
def reloadParameters(self): | |||
# Remove all previous parameters | |||
self.close() | |||
hasGroup, groupId = patchcanvas.getPluginAsGroup(self.fPluginId) | |||
if not hasGroup: | |||
self.fGroupId = None | |||
return | |||
self.fGroupId = groupId | |||
# Reset | |||
self.fParameterList = [] | |||
if gCarla.host is None: | |||
return | |||
parameterCount = gCarla.host.get_parameter_count(self.fPluginId) | |||
if parameterCount <= 0 or parameterCount > 25: | |||
return | |||
for i in range(parameterCount): | |||
paramInfo = gCarla.host.get_parameter_info(self.fPluginId, i) | |||
paramData = gCarla.host.get_parameter_data(self.fPluginId, i) | |||
paramRanges = gCarla.host.get_parameter_ranges(self.fPluginId, i) | |||
paramValue = gCarla.host.get_current_parameter_value(self.fPluginId, i) | |||
if paramData['type'] not in (PARAMETER_INPUT, PARAMETER_OUTPUT): | |||
#if paramData['type'] != PARAMETER_INPUT: | |||
continue | |||
if (paramData['hints'] & PARAMETER_IS_AUTOMABLE) == 0: | |||
continue | |||
portId = -i-1 | |||
portMode = patchcanvas.PORT_MODE_OUTPUT if paramData['type'] == PARAMETER_OUTPUT else patchcanvas.PORT_MODE_INPUT | |||
portValue = (paramValue - paramRanges['min']) / (paramRanges['max'] - paramRanges['min']) | |||
patchcanvas.addPort(groupId, portId, paramInfo['name'], portMode, patchcanvas.PORT_TYPE_PARAMETER) | |||
patchcanvas.setPortValue(groupId, portId, portValue) | |||
self.fParameterList.append((paramData['type'], i, paramRanges['min'], paramRanges['max'])) | |||
#------------------------------------------------------------------ | |||
def setId(self, idx): | |||
self.fPluginId = idx | |||
def setParameterValue(self, parameterId, value): | |||
if self.fGroupId is None: | |||
return | |||
paramRanges = gCarla.host.get_parameter_ranges(self.fPluginId, parameterId) | |||
portValue = (value - paramRanges['min']) / (paramRanges['max'] - paramRanges['min']) | |||
patchcanvas.setPortValue(self.fGroupId, -parameterId-1, portValue) | |||
#------------------------------------------------------------------ | |||
def idleSlow(self): | |||
# Update parameter outputs | |||
for paramType, paramIndex, paramMin, paramMax in self.fParameterList: | |||
if paramType == PARAMETER_OUTPUT: | |||
portValue = (gCarla.host.get_current_parameter_value(self.fPluginId, paramIndex) - paramMin) / (paramMax - paramMin) | |||
patchcanvas.setPortValue(self.fGroupId, -paramIndex-1, portValue) | |||
# ------------------------------------------------------------------------------------------------ | |||
# Patchbay widget | |||
@@ -208,6 +296,7 @@ class CarlaPatchbayW(QFrame): | |||
parent.PatchbayPortAddedCallback.connect(self.slot_handlePatchbayPortAddedCallback) | |||
parent.PatchbayPortRemovedCallback.connect(self.slot_handlePatchbayPortRemovedCallback) | |||
parent.PatchbayPortRenamedCallback.connect(self.slot_handlePatchbayPortRenamedCallback) | |||
parent.PatchbayPortValueChangedCallback.connect(self.slot_handlePatchbayPortValueChangedCallback) | |||
parent.PatchbayConnectionAddedCallback.connect(self.slot_handlePatchbayConnectionAddedCallback) | |||
parent.PatchbayConnectionRemovedCallback.connect(self.slot_handlePatchbayConnectionRemovedCallback) | |||
@@ -219,16 +308,15 @@ class CarlaPatchbayW(QFrame): | |||
# ----------------------------------------------------------------- | |||
def addPlugin(self, pluginId, isProjectLoading): | |||
if not self.fIsOnlyPatchbay: | |||
self.fPluginCount += 1 | |||
return | |||
pitem = PluginEdit(self, pluginId) | |||
if self.fIsOnlyPatchbay: | |||
pitem = PluginEdit(self, pluginId) | |||
else: | |||
pitem = PluginInfo(self, pluginId) | |||
self.fPluginList.append(pitem) | |||
self.fPluginCount += 1 | |||
if not isProjectLoading: | |||
if self.fIsOnlyPatchbay and not isProjectLoading: | |||
gCarla.host.set_active(pluginId, True) | |||
def removePlugin(self, pluginId): | |||
@@ -237,10 +325,6 @@ class CarlaPatchbayW(QFrame): | |||
if pluginId in self.fSelectedPlugins: | |||
self.clearSideStuff() | |||
if not self.fIsOnlyPatchbay: | |||
self.fPluginCount -= 1 | |||
return | |||
if pluginId >= self.fPluginCount: | |||
return | |||
@@ -887,6 +971,10 @@ class CarlaPatchbayW(QFrame): | |||
patchcanvas.renamePort(groupId, portId, newPortName) | |||
QTimer.singleShot(0, self.fMiniCanvasPreview.update) | |||
@pyqtSlot(int, int, float) | |||
def slot_handlePatchbayPortValueChangedCallback(self, groupId, portId, value): | |||
patchcanvas.setPortValue(groupId, portId, value) | |||
@pyqtSlot(int, int, int, int, int) | |||
def slot_handlePatchbayConnectionAddedCallback(self, connectionId, groupOutId, portOutId, groupInId, portInId): | |||
patchcanvas.connectPorts(connectionId, groupOutId, portOutId, groupInId, portInId) | |||
@@ -909,6 +997,12 @@ class CarlaPatchbayW(QFrame): | |||
patchcanvas.clear() | |||
if gCarla.host.is_engine_running(): | |||
gCarla.host.patchbay_refresh() | |||
for pitem in self.fPluginList: | |||
if pitem is None: | |||
break | |||
pitem.reloadAll() | |||
QTimer.singleShot(1000 if self.fParent.fSavedSettings[CARLA_KEY_CANVAS_EYE_CANDY] else 0, self.fMiniCanvasPreview.update) | |||
@pyqtSlot() | |||
@@ -999,10 +1093,9 @@ def canvasCallback(action, value1, value2, valueStr): | |||
pass | |||
elif action == patchcanvas.ACTION_PORTS_CONNECT: | |||
portIdA = value1 | |||
portIdB = value2 | |||
gOut, pOut, gIn, pIn = [int(i) for i in valueStr.split(":")] | |||
if not gCarla.host.patchbay_connect(portIdA, portIdB): | |||
if not gCarla.host.patchbay_connect(gOut, pOut, gIn, pIn): | |||
print("Connection failed:", gCarla.host.get_last_error()) | |||
elif action == patchcanvas.ACTION_PORTS_DISCONNECT: | |||
@@ -70,7 +70,7 @@ ACTION_GROUP_SPLIT = 2 # group_id, N, N | |||
ACTION_GROUP_JOIN = 3 # group_id, N, N | |||
ACTION_PORT_INFO = 4 # port_id, N, N | |||
ACTION_PORT_RENAME = 5 # port_id, N, new_name | |||
ACTION_PORTS_CONNECT = 6 # out_id, in_id, N | |||
ACTION_PORTS_CONNECT = 6 # N, N, "outG:outP:inG:inP" | |||
ACTION_PORTS_DISCONNECT = 7 # conn_id, N, N | |||
ACTION_PLUGIN_CLONE = 8 # plugin_id, N, N | |||
ACTION_PLUGIN_EDIT = 9 # plugin_id, N, N | |||
@@ -140,6 +140,7 @@ class group_dict_t(object): | |||
'group_name', | |||
'split', | |||
'icon', | |||
'plugin_id', | |||
'widgets' | |||
] | |||
@@ -444,6 +445,7 @@ def addGroup(group_id, group_name, split=SPLIT_UNDEF, icon=ICON_APPLICATION): | |||
group_dict.group_name = group_name | |||
group_dict.split = bool(split == SPLIT_YES) | |||
group_dict.icon = icon | |||
group_dict.plugin_id = -1 | |||
group_dict.widgets = [group_box, None] | |||
if split == SPLIT_YES: | |||
@@ -759,12 +761,24 @@ def setGroupIcon(group_id, icon): | |||
qCritical("PatchCanvas::setGroupIcon(%i, %s) - unable to find group to change icon" % (group_id, icon2str(icon))) | |||
def getPluginAsGroup(plugin_id): | |||
if canvas.debug: | |||
qDebug("PatchCanvas::getPluginAsGroup(%i)" % plugin_id) | |||
for group in canvas.group_list: | |||
if group.plugin_id == plugin_id: | |||
return (True, group.group_id) | |||
qCritical("PatchCanvas::getPluginAsGroup(%i) - no such plugin" % plugin_id) | |||
return (False, -1) | |||
def setGroupAsPlugin(group_id, plugin_id, hasUi): | |||
if canvas.debug: | |||
qDebug("PatchCanvas::setGroupAsPlugin(%i, %i, %s)" % (group_id, plugin_id, bool2str(hasUi))) | |||
for group in canvas.group_list: | |||
if group.group_id == group_id: | |||
group.plugin_id = plugin_id | |||
group.widgets[0].setAsPlugin(plugin_id, hasUi) | |||
if group.split and group.widgets[1]: | |||
@@ -849,6 +863,17 @@ def renamePort(group_id, port_id, new_port_name): | |||
qCritical("PatchCanvas::renamePort(%i, %i, %s) - Unable to find port to rename" % (group_id, port_id, new_port_name.encode())) | |||
def setPortValue(group_id, port_id, value): | |||
if canvas.debug: | |||
qDebug("PatchCanvas::setPortValue(%i, %i, %f)" % (group_id, port_id, value)) | |||
for port in canvas.port_list: | |||
if port.group_id == group_id and port.port_id == port_id: | |||
port.widget.setPortValue(value) | |||
return | |||
qCritical("PatchCanvas::setPortValue(%i, %i, %f) - Unable to find port" % (group_id, port_id, value)) | |||
def connectPorts(connection_id, group_out_id, port_out_id, group_in_id, port_in_id): | |||
if canvas.debug: | |||
qDebug("PatchCanvas::connectPorts(%i, %i, %i, %i, %i)" % (connection_id, group_out_id, port_out_id, group_in_id, port_in_id)) | |||
@@ -971,9 +996,10 @@ def handlePluginRemoved(plugin_id): | |||
qDebug("PatchCanvas::handlePluginRemoved(%i)" % plugin_id) | |||
for group in canvas.group_list: | |||
if group.widgets[0].m_plugin_id < plugin_id: | |||
if group.plugin_id < plugin_id: | |||
continue | |||
group.plugin_id -= 1 | |||
group.widgets[0].m_plugin_id -= 1 | |||
if group.split and group.widgets[1]: | |||
@@ -1761,6 +1787,8 @@ class CanvasPort(QGraphicsItem): | |||
self.m_port_font.setPointSize(canvas.theme.port_font_size) | |||
self.m_port_font.setWeight(canvas.theme.port_font_state) | |||
self.m_port_value = 1.0 | |||
self.m_line_mov = None | |||
self.m_hover_item = None | |||
self.m_last_selected_state = False | |||
@@ -1770,6 +1798,9 @@ class CanvasPort(QGraphicsItem): | |||
self.setFlags(QGraphicsItem.ItemIsSelectable) | |||
def getGroupId(self): | |||
return self.m_group_id | |||
def getPortId(self): | |||
return self.m_port_id | |||
@@ -1799,6 +1830,13 @@ class CanvasPort(QGraphicsItem): | |||
self.m_port_type = port_type | |||
self.update() | |||
def setPortValue(self, value): | |||
if self.m_port_value == value: | |||
return | |||
self.m_port_value = value | |||
self.update() | |||
def setPortName(self, port_name): | |||
if QFontMetrics(self.m_port_font).width(port_name) < QFontMetrics(self.m_port_font).width(self.m_port_name): | |||
QTimer.singleShot(0, canvas.scene.update) | |||
@@ -1881,19 +1919,19 @@ class CanvasPort(QGraphicsItem): | |||
connection.widget.setLocked(False) | |||
if self.m_hover_item: | |||
check = False | |||
# TODO: a better way to check already existing connection | |||
for connection in canvas.connection_list: | |||
if ( (connection.port_out_id == self.m_port_id and connection.port_in_id == self.m_hover_item.getPortId()) or | |||
(connection.port_out_id == self.m_hover_item.getPortId() and connection.port_in_id == self.m_port_id) ): | |||
canvas.callback(ACTION_PORTS_DISCONNECT, connection.connection_id, 0, "") | |||
check = True | |||
break | |||
if not check: | |||
else: | |||
if self.m_port_mode == PORT_MODE_OUTPUT: | |||
canvas.callback(ACTION_PORTS_CONNECT, self.m_port_id, self.m_hover_item.getPortId(), "") | |||
conn = "%i:%i:%i:%i" % (self.m_group_id, self.m_port_id, self.m_hover_item.getGroupId(), self.m_hover_item.getPortId()) | |||
canvas.callback(ACTION_PORTS_CONNECT, 0, 0, conn) | |||
else: | |||
canvas.callback(ACTION_PORTS_CONNECT, self.m_hover_item.getPortId(), self.m_port_id, "") | |||
conn = "%i:%i:%i:%i" % (self.m_hover_item.getGroupId(), self.m_hover_item.getPortId(), self.m_group_id, self.m_port_id) | |||
canvas.callback(ACTION_PORTS_CONNECT, 0, 0, conn) | |||
canvas.scene.clearSelection() | |||
@@ -2043,15 +2081,39 @@ class CanvasPort(QGraphicsItem): | |||
polygon += QPointF(poly_locx[3], canvas.theme.port_height) | |||
polygon += QPointF(poly_locx[4], canvas.theme.port_height) | |||
if canvas.theme.port_bg_pixmap: | |||
portRect = polygon.boundingRect() | |||
portPos = portRect.topLeft() | |||
painter.drawTiledPixmap(portRect, canvas.theme.port_bg_pixmap, portPos) | |||
if self.m_port_value == 1.0 or canvas.theme.port_bg_pixmap: | |||
# normal paint | |||
if canvas.theme.port_bg_pixmap: | |||
portRect = polygon.boundingRect() | |||
portPos = portRect.topLeft() | |||
painter.drawTiledPixmap(portRect, canvas.theme.port_bg_pixmap, portPos) | |||
else: | |||
painter.setBrush(poly_color) #.lighter(200)) | |||
painter.setPen(poly_pen) | |||
painter.drawPolygon(polygon) | |||
else: | |||
painter.setBrush(poly_color) | |||
# incomplete paint | |||
painter.setPen(poly_pen) | |||
painter.drawPolygon(polygon) | |||
painter.setPen(poly_pen) | |||
painter.drawPolygon(polygon) | |||
sub = QPolygonF() | |||
if self.m_port_mode == PORT_MODE_INPUT: | |||
sub += QPointF(poly_locx[0], 0) | |||
sub += QPointF(poly_locx[2]*self.m_port_value, 0) | |||
sub += QPointF(poly_locx[2]*self.m_port_value, canvas.theme.port_height) | |||
sub += QPointF(poly_locx[0], canvas.theme.port_height) | |||
else: | |||
sub += QPointF(poly_locx[2], 0) | |||
sub += QPointF(poly_locx[0]*self.m_port_value, 0) | |||
sub += QPointF(poly_locx[0]*self.m_port_value, canvas.theme.port_height) | |||
sub += QPointF(poly_locx[2], canvas.theme.port_height) | |||
painter.setBrush(poly_color) | |||
painter.setPen(poly_pen) | |||
painter.drawPolygon(polygon.intersected(sub)) | |||
painter.setPen(text_pen) | |||
painter.setFont(self.m_port_font) | |||
@@ -255,6 +255,8 @@ const char* EngineCallbackOpcode2Str(const EngineCallbackOpcode opcode) noexcept | |||
return "ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED"; | |||
case ENGINE_CALLBACK_PATCHBAY_PORT_RENAMED: | |||
return "ENGINE_CALLBACK_PATCHBAY_PORT_RENAMED"; | |||
case ENGINE_CALLBACK_PATCHBAY_PORT_VALUE_CHANGED: | |||
return "ENGINE_CALLBACK_PATCHBAY_PORT_VALUE_CHANGED"; | |||
case ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED: | |||
return "ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED"; | |||
case ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED: | |||