Browse Source

In-canvas parameters experiment

tags/1.9.4
falkTX 10 years ago
parent
commit
a4603ef159
14 changed files with 321 additions and 94 deletions
  1. +20
    -12
      source/backend/CarlaBackend.h
  2. +1
    -1
      source/backend/CarlaEngine.hpp
  3. +5
    -3
      source/backend/CarlaHost.h
  4. +55
    -16
      source/backend/engine/CarlaEngine.cpp
  5. +11
    -7
      source/backend/engine/CarlaEngineJack.cpp
  6. +4
    -2
      source/backend/engine/CarlaEngineNative.cpp
  7. +3
    -4
      source/backend/standalone/CarlaStandalone.cpp
  8. +5
    -0
      source/carla
  9. +2
    -2
      source/carla-plugin
  10. +25
    -17
      source/carla_backend.py
  11. +5
    -2
      source/carla_host.py
  12. +106
    -13
      source/carla_patchbay.py
  13. +77
    -15
      source/patchcanvas.py
  14. +2
    -0
      source/utils/CarlaBackendUtils.hpp

+ 20
- 12
source/backend/CarlaBackend.h View File

@@ -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;



+ 1
- 1
source/backend/CarlaEngine.hpp View File

@@ -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.


+ 5
- 3
source/backend/CarlaHost.h View File

@@ -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.


+ 55
- 16
source/backend/engine/CarlaEngine.cpp View File

@@ -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


+ 11
- 7
source/backend/engine/CarlaEngineJack.cpp View File

@@ -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);


+ 4
- 2
source/backend/engine/CarlaEngineNative.cpp View File

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


+ 3
- 4
source/backend/standalone/CarlaStandalone.cpp View File

@@ -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";


+ 5
- 0
source/carla View File

@@ -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()

# -----------------------------------------------------------------



+ 2
- 2
source/carla-plugin View File

@@ -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):


+ 25
- 17
source/carla_backend.py View File

@@ -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]


+ 5
- 2
source/carla_host.py View File

@@ -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)


+ 106
- 13
source/carla_patchbay.py View File

@@ -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:


+ 77
- 15
source/patchcanvas.py View File

@@ -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)


+ 2
- 0
source/utils/CarlaBackendUtils.hpp View File

@@ -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:


Loading…
Cancel
Save