Browse Source

Allow custom properties per plugin, use it to save is-skin-compact

tags/1.9.6
falkTX 9 years ago
parent
commit
f7bc330102
13 changed files with 146 additions and 25 deletions
  1. +5
    -5
      source/backend/CarlaBackend.h
  2. +40
    -0
      source/backend/engine/CarlaEngineNative.cpp
  3. +6
    -2
      source/backend/plugin/CarlaPlugin.cpp
  4. +3
    -0
      source/backend/plugin/CarlaPluginBridge.cpp
  5. +3
    -0
      source/backend/plugin/CarlaPluginDSSI.cpp
  6. +3
    -0
      source/backend/plugin/CarlaPluginFluidSynth.cpp
  7. +3
    -0
      source/backend/plugin/CarlaPluginLV2.cpp
  8. +3
    -0
      source/backend/plugin/CarlaPluginLinuxSampler.cpp
  9. +3
    -0
      source/backend/plugin/CarlaPluginNative.cpp
  10. +23
    -2
      source/carla_backend.py
  11. +28
    -1
      source/carla_host.py
  12. +11
    -13
      source/native-plugins/resources/carla-plugin
  13. +15
    -2
      source/widgets/racklistwidget.py

+ 5
- 5
source/backend/CarlaBackend.h View File

@@ -352,6 +352,11 @@ static const char* const CUSTOM_DATA_TYPE_BOOLEAN = "http://kxstudio.sf.net/ns/c
*/
static const char* const CUSTOM_DATA_TYPE_CHUNK = "http://kxstudio.sf.net/ns/carla/chunk";

/*!
* Property type URI.
*/
static const char* const CUSTOM_DATA_TYPE_PROPERTY = "http://kxstudio.sf.net/ns/carla/property";

/*!
* String type URI.
*/
@@ -370,11 +375,6 @@ static const char* const CUSTOM_DATA_TYPE_STRING = "http://kxstudio.sf.net/ns/ca
* @{
*/

/*!
* Plugin options key.
*/
static const char* const CUSTOM_DATA_KEY_PLUGIN_OPTIONS = "CarlaPluginOptions";

/*!
* UI position key.
*/


+ 40
- 0
source/backend/engine/CarlaEngineNative.cpp View File

@@ -889,6 +889,35 @@ protected:
fUiServer.flushMessages();
}

void uiServerSendPluginProperties(CarlaPlugin* const plugin)
{
const CarlaMutexLocker cml(fUiServer.getPipeLock());

const uint pluginId(plugin->getId());

uint32_t count = plugin->getCustomDataCount();
std::sprintf(fTmpBuf, "CUSTOM_DATA_COUNT_%i:%i\n", pluginId, count);
fUiServer.writeMessage(fTmpBuf);

for (uint32_t i=0; i<count; ++i)
{
const CustomData& customData(plugin->getCustomData(i));
CARLA_SAFE_ASSERT_CONTINUE(customData.isValid());

if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_PROPERTY) != 0)
continue;

std::sprintf(fTmpBuf, "CUSTOM_DATA_%i:%i\n", pluginId, i);
fUiServer.writeMessage(fTmpBuf);

fUiServer.writeAndFixMessage(customData.type);
fUiServer.writeAndFixMessage(customData.key);
fUiServer.writeAndFixMessage(customData.value);
}

fUiServer.flushMessages();
}

void uiServerCallback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const float value3, const char* const valueStr)
{
if (! fIsRunning)
@@ -900,6 +929,16 @@ protected:

switch (action)
{
case ENGINE_CALLBACK_UPDATE:
plugin = getPlugin(pluginId);

if (plugin != nullptr && plugin->isEnabled())
{
CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
uiServerSendPluginProperties(plugin);
}
break;

case ENGINE_CALLBACK_RELOAD_INFO:
plugin = getPlugin(pluginId);

@@ -940,6 +979,7 @@ protected:
uiServerSendPluginInfo(plugin);
uiServerSendPluginParameters(plugin);
uiServerSendPluginPrograms(plugin);
uiServerSendPluginProperties(plugin);
}
break;



+ 6
- 2
source/backend/plugin/CarlaPlugin.cpp View File

@@ -622,6 +622,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
CARLA_SAFE_ASSERT_CONTINUE(stateCustomData != nullptr);
CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->isValid());

const char* const type(stateCustomData->type);
const char* const key(stateCustomData->key);

if (getType() == PLUGIN_DSSI && (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0))
@@ -629,7 +630,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
if (usesMultiProgs && std::strcmp(key, "midiPrograms") == 0)
continue;

setCustomData(stateCustomData->type, stateCustomData->key, stateCustomData->value, true);
setCustomData(type, key, stateCustomData->value, true);
}

// ---------------------------------------------------------------
@@ -797,6 +798,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
CARLA_SAFE_ASSERT_CONTINUE(stateCustomData != nullptr);
CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->isValid());

const char* const type(stateCustomData->type);
const char* const key(stateCustomData->key);

if (getType() == PLUGIN_DSSI && (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0))
@@ -804,7 +806,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
if (usesMultiProgs && std::strcmp(key, "midiPrograms") == 0)
continue;

setCustomData(stateCustomData->type, stateCustomData->key, stateCustomData->value, true);
setCustomData(type, key, stateCustomData->value, true);
}

// ---------------------------------------------------------------
@@ -845,6 +847,8 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
setCtrlChannel(stateSave.ctrlChannel, true, true);
setActive(stateSave.active, true, true);
#endif

pData->engine->callback(ENGINE_CALLBACK_UPDATE, pData->id, 0, 0, 0.0f, nullptr);
}

bool CarlaPlugin::saveStateToFile(const char* const filename)


+ 3
- 0
source/backend/plugin/CarlaPluginBridge.cpp View File

@@ -1080,6 +1080,9 @@ public:
CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(value != nullptr,);

if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
return CarlaPlugin::setCustomData(type, key, value, sendGui);

if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) == 0 && std::strcmp(key, "__CarlaPingOnOff__") == 0)
{
const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);


+ 3
- 0
source/backend/plugin/CarlaPluginDSSI.cpp View File

@@ -567,6 +567,9 @@ public:
CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
carla_debug("CarlaPluginDSSI::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));

if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
return CarlaPlugin::setCustomData(type, key, value, sendGui);

if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0)
return carla_stderr2("CarlaPluginDSSI::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));



+ 3
- 0
source/backend/plugin/CarlaPluginFluidSynth.cpp View File

@@ -462,6 +462,9 @@ public:
CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0',);
carla_debug("CarlaPluginFluidSynth::setCustomData(%s, \"%s\", \"%s\", %s)", type, key, value, bool2str(sendGui));

if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
return CarlaPlugin::setCustomData(type, key, value, sendGui);

if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0)
return carla_stderr2("CarlaPluginFluidSynth::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));



+ 3
- 0
source/backend/plugin/CarlaPluginLV2.cpp View File

@@ -1135,6 +1135,9 @@ public:
CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
carla_debug("CarlaPluginLV2::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));

if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
return CarlaPlugin::setCustomData(type, key, value, sendGui);

// we should only call state restore once
// so inject this in CarlaPlugin::loadSaveState
if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) == 0 && std::strcmp(key, "CarlaLoadLv2StateNow") == 0 && std::strcmp(value, "true") == 0)


+ 3
- 0
source/backend/plugin/CarlaPluginLinuxSampler.cpp View File

@@ -429,6 +429,9 @@ public:
CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0',);
carla_debug("CarlaPluginLinuxSampler::setCustomData(%s, \"%s\", \"%s\", %s)", type, key, value, bool2str(sendGui));

if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
return CarlaPlugin::setCustomData(type, key, value, sendGui);

if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0)
return carla_stderr2("CarlaPluginLinuxSampler::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));



+ 3
- 0
source/backend/plugin/CarlaPluginNative.cpp View File

@@ -607,6 +607,9 @@ public:
CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
carla_debug("CarlaPluginNative::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));

if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
return CarlaPlugin::setCustomData(type, key, value, sendGui);

if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0 && std::strcmp(type, CUSTOM_DATA_TYPE_CHUNK) != 0)
return carla_stderr2("CarlaPluginNative::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is invalid", type, key, value, bool2str(sendGui));



+ 23
- 2
source/carla_backend.py View File

@@ -312,6 +312,9 @@ CUSTOM_DATA_TYPE_BOOLEAN = "http://kxstudio.sf.net/ns/carla/boolean"
# Chunk type URI.
CUSTOM_DATA_TYPE_CHUNK = "http://kxstudio.sf.net/ns/carla/chunk"

# Property type URI.
CUSTOM_DATA_TYPE_PROPERTY = "http://kxstudio.sf.net/ns/carla/property"

# String type URI.
CUSTOM_DATA_TYPE_STRING = "http://kxstudio.sf.net/ns/carla/string"

@@ -2641,6 +2644,8 @@ class PluginStoreInfo(object):
'midiProgramCount',
'midiProgramCurrent',
'midiProgramData',
'customDataCount',
'customData',
'peaks'
]

@@ -2814,7 +2819,7 @@ class CarlaHostPlugin(CarlaHostMeta):
return self.fPluginsInfo[pluginId].midiProgramData[midiProgramId]

def get_custom_data(self, pluginId, customDataId):
return PyCustomData
return self.fPluginsInfo[pluginId].customData[customDataId]

def get_chunk_data(self, pluginId):
return ""
@@ -2829,7 +2834,7 @@ class CarlaHostPlugin(CarlaHostMeta):
return self.fPluginsInfo[pluginId].midiProgramCount

def get_custom_data_count(self, pluginId):
return 0
return self.fPluginsInfo[pluginId].customDataCount

def get_parameter_text(self, pluginId, parameterId):
return ""
@@ -2978,6 +2983,8 @@ class CarlaHostPlugin(CarlaHostMeta):
info.midiProgramCount = 0
info.midiProgramCurrent = -1
info.midiProgramData = []
info.customDataCount = 0
info.customData = []
info.peaks = [0.0, 0.0, 0.0, 0.0]
self.fPluginsInfo.append(info)

@@ -3037,6 +3044,16 @@ class CarlaHostPlugin(CarlaHostMeta):
for x in range(count):
self.fPluginsInfo[pluginId].midiProgramData.append(PyMidiProgramData)

def _set_customDataCount(self, pluginId, count):
self.fPluginsInfo[pluginId].customDataCount = count

# clear
self.fPluginsInfo[pluginId].customData = []

# add placeholders
for x in range(count):
self.fPluginsInfo[pluginId].customData.append(PyCustomData)

def _set_parameterInfo(self, pluginId, paramIndex, info):
if pluginId < len(self.fPluginsInfo) and paramIndex < self.fPluginsInfo[pluginId].parameterCount:
self.fPluginsInfo[pluginId].parameterInfo[paramIndex] = info
@@ -3079,6 +3096,10 @@ class CarlaHostPlugin(CarlaHostMeta):
if mpIndex < self.fPluginsInfo[pluginId].midiProgramCount:
self.fPluginsInfo[pluginId].midiProgramData[mpIndex] = data

def _set_customData(self, pluginId, cdIndex, data):
if cdIndex < self.fPluginsInfo[pluginId].customDataCount:
self.fPluginsInfo[pluginId].customData[cdIndex] = data

def _set_peaks(self, pluginId, in1, in2, out1, out2):
self.fPluginsInfo[pluginId].peaks = [in1, in2, out1, out2]



+ 28
- 1
source/carla_host.py View File

@@ -386,6 +386,8 @@ class HostWindow(QMainWindow):
host.NoteOnCallback.connect(self.slot_handleNoteOnCallback)
host.NoteOffCallback.connect(self.slot_handleNoteOffCallback)

host.UpdateCallback.connect(self.slot_handleUpdateCallback)

host.PatchbayClientAddedCallback.connect(self.slot_handlePatchbayClientAddedCallback)
host.PatchbayClientRemovedCallback.connect(self.slot_handlePatchbayClientRemovedCallback)
host.PatchbayClientRenamedCallback.connect(self.slot_handlePatchbayClientRenamedCallback)
@@ -1495,6 +1497,32 @@ class HostWindow(QMainWindow):
if pluginId in self.fSelectedPlugins:
self.ui.keyboard.sendNoteOff(note, False)

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

@pyqtSlot(int)
def slot_handleUpdateCallback(self, pluginId):
pitem = self.getPluginItem(pluginId)

if pitem is None:
return

wasCompacted = pitem.isCompacted()
isCompacted = wasCompacted

for i in range(self.host.get_custom_data_count(pluginId)):
cdata = self.host.get_custom_data(pluginId, i)

if cdata['type'] == CUSTOM_DATA_TYPE_PROPERTY and cdata['key'] == "CarlaSkinIsCompacted":
isCompacted = bool(cdata['value'] == "true")
break
else:
return

if wasCompacted == isCompacted:
return

pitem.recreateWidget(True)

# --------------------------------------------------------------------------------------------------------
# MiniCanvas stuff

@@ -1581,7 +1609,6 @@ class HostWindow(QMainWindow):
if pitem is None:
return

self.ui.listWidget.customClearSelection()
pitem.recreateWidget()

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


+ 11
- 13
source/native-plugins/resources/carla-plugin View File

@@ -312,19 +312,17 @@ class CarlaMiniW(ExternalUI, HostWindow):
name = self.readlineblock().replace("\r", "\n")
self.host._set_midiProgramData(pluginId, midiProgId, {'bank': bank, 'program': program, 'name': name})

elif msg == "complete-license":
license = self.readlineblock().replace("\r", "\n")
self.host.fCompleteLicenseText = license

elif msg == "juce-version":
version = self.readlineblock().replace("\r", "\n")
self.host.fJuceVersion = version

elif msg == "file-exts":
exts = self.readlineblock().replace("\r", "\n")
self.host.fSupportedFileExts = exts
# only now we know the supported extensions
self.fDirModel.setNameFilters(exts.split(";"))
elif msg.startswith("CUSTOM_DATA_COUNT_"):
pluginId, count = [int(i) for i in msg.replace("CUSTOM_DATA_COUNT_", "").split(":")]
self.host._set_customDataCount(pluginId, count)

elif msg.startswith("CUSTOM_DATA_"):
pluginId, customDataId = [int(i) for i in msg.replace("CUSTOM_DATA_", "").split(":")]

type_ = self.readlineblock().replace("\r", "\n")
key = self.readlineblock().replace("\r", "\n")
value = self.readlineblock().replace("\r", "\n")
self.host._set_customData(pluginId, customDataId, {'type': type_, 'key': key, 'value': value})

elif msg == "max-plugin-number":
maxnum = int(self.readlineblock())


+ 15
- 2
source/widgets/racklistwidget.py View File

@@ -67,13 +67,19 @@ class RackListItem(QListWidgetItem):
'useSkins': useSkins
}

for i in range(self.host.get_custom_data_count(pluginId)):
cdata = self.host.get_custom_data(pluginId, i)
if cdata['type'] == CUSTOM_DATA_TYPE_PROPERTY and cdata['key'] == "CarlaSkinIsCompacted":
self.fOptions['compact'] = bool(cdata['value'] == "true")
break

self.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)
#self.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled|Qt.ItemIsDragEnabled)

# ----------------------------------------------------------------------------------------------------
# Set-up GUI

self.recreateWidget()
self.recreateWidget(firstInit = True)

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

@@ -97,6 +103,9 @@ class RackListItem(QListWidgetItem):
widget.deleteLater()
del widget

def isCompacted(self):
return self.fOptions['compact']

def getEditDialog(self):
if self.fWidget is None:
return None
@@ -125,7 +134,7 @@ class RackListItem(QListWidgetItem):

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

def recreateWidget(self, invertCompactOption = False):
def recreateWidget(self, invertCompactOption = False, firstInit = False):
if invertCompactOption:
self.fOptions['compact'] = not self.fOptions['compact']

@@ -138,6 +147,10 @@ class RackListItem(QListWidgetItem):

self.fParent.setItemWidget(self, self.fWidget)

if not firstInit:
self.host.set_custom_data(self.fPluginId, CUSTOM_DATA_TYPE_PROPERTY,
"CarlaSkinIsCompacted", "true" if self.fOptions['compact'] else "false")

# ------------------------------------------------------------------------------------------------------------
# Rack Widget



Loading…
Cancel
Save