Browse Source

Carla: Implement bridge state restore

tags/v0.9.0
falkTX 12 years ago
parent
commit
7044f9288e
7 changed files with 794 additions and 25 deletions
  1. +0
    -1
      .gitignore
  2. +366
    -18
      c++/carla-bridge/carla_bridge_plugin.cpp
  3. +9
    -2
      c++/carla-bridge/qtcreator/carla-bridge-plugin.pro
  4. +257
    -0
      c++/carla/Shared.cpp
  5. +151
    -0
      c++/carla/Shared.hpp
  6. +4
    -0
      doc/TODO
  7. +7
    -4
      src/shared_carla.py

+ 0
- 1
.gitignore View File

@@ -112,7 +112,6 @@ c++/carla-native/zynaddsubfx/UI/VirKeyboard.h
_/
all-recheck
c++/caitlyn/
c++/carla/
c++/carla-backend/carla-dynamic.lv2/
c++/carla-backend/carla_backend_lv2.cpp
c++/carla-backend/carla_backend_vst.cpp


+ 366
- 18
c++/carla-bridge/carla_bridge_plugin.cpp View File

@@ -20,10 +20,14 @@
#include "carla_bridge_client.hpp"
#include "carla_bridge_toolkit.hpp"
#include "carla_plugin.hpp"
#include "../carla/Shared.hpp"

#include <set>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QTextStream>
#include <QtCore/QThread>
#include <QtXml/QDomDocument>

#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
# include <QtWidgets/QApplication>
@@ -221,12 +225,12 @@ public:
m_uiShow = showUI;
}

void guiClosedCallback();

protected:
QApplication* app;
CarlaBackend::CarlaPluginGUI* gui;

void guiClosedCallback();

private:
bool m_hasUI;
bool m_uiQuit;
@@ -253,6 +257,10 @@ public:
msgTimerGUI = 0;
msgTimerOSC = 0;

needsResize = 0;
nextWidth = 0;
nextHeight = 0;

engine = nullptr;
plugin = nullptr;
}
@@ -276,15 +284,12 @@ public:
if (! plugin)
return;

// create window if needed
bool guiResizable;
CarlaBackend::GuiType guiType;
plugin->getGuiInfo(&guiType, &guiResizable);

CarlaBridgeToolkitPlugin* const plugToolkit = (CarlaBridgeToolkitPlugin*)m_toolkit;

qWarning("----------------------------------------------------- trying..., %s", CarlaBackend::GuiType2Str(guiType));

if (guiType == CarlaBackend::GUI_INTERNAL_QT4 || guiType == CarlaBackend::GUI_INTERNAL_COCOA || guiType == CarlaBackend::GUI_INTERNAL_HWND || guiType == CarlaBackend::GUI_INTERNAL_X11)
{
plugin->setGuiContainer(plugToolkit->getContainer());
@@ -332,10 +337,264 @@ public:
CARLA_ASSERT(plugin);

this->plugin = plugin;

// load carla plugin preset if possible
if (const char* const pName = plugin->name())
{
QFile pFile(QDir::currentPath() + QDir::separator() + pName + ".carxs");
qDebug("Trying to load plugin preset file '%s'", pFile.fileName().toUtf8().constData());

if (! /*(*/pFile.exists() /*&& pFile.isReadable())*/)
{
qDebug("Plugin preset file doesn't exist or is not readable");
return;
}

if (! pFile.open(QFile::ReadOnly))
{
qWarning("Plugin preset file read failed");
return;
}

QDomDocument xml;
xml.setContent(pFile.readAll());

QDomElement xmlNode(xml.documentElement());

if (xmlNode.tagName() == "CARLA-PRESET")
{
loadStateDict(getSaveStateDictFromXML(xmlNode));
}
else
qWarning("Plugin preset file is not valid or corrupted");

pFile.close();
}
}

// ---------------------------------------------------------------------

void loadStateDict(const CarlaSaveState* const content)
{
CARLA_ASSERT(content);

if (! content)
return;

qDebug("Loading plugin state now...");

// ---------------------------------------------------------------------
// Part 1 - set custom data (except chunks)

foreach (const CarlaStateCustomData& customData, content->customData)
{
if (customData.type != CUSTOM_DATA_CHUNK)
{
const char* const type = customData.type.toUtf8().constData();
const char* const key = customData.key.toUtf8().constData();
const char* const value = customData.value.toUtf8().constData();

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

// ---------------------------------------------------------------------
// Part 2 - set program

int32_t programId = -1;

if (! content->currentProgramName.isEmpty())
{
const uint32_t programCount = plugin->programCount();

char strBuf[STR_MAX] = { 0 };
plugin->getProgramName(content->currentProgramIndex, strBuf);
QString testProgramName(strBuf);

// Program name matches
if (content->currentProgramName == testProgramName)
{
programId = content->currentProgramIndex;
}

// index < count
else if (content->currentProgramIndex < (int32_t)programCount)
{
programId = content->currentProgramIndex;
}

// index not valid, try to find by name
else
{
for (uint32_t i=0; i < programCount; i++)
{
plugin->getProgramName(i, strBuf);
testProgramName = QString(strBuf);

if (content->currentProgramName == testProgramName)
{
programId = i;
break;
}
}
}
}

// set program now, if valid
if (programId >= 0)
{
plugin->setProgram(programId, true, true, false, true);
}

// ---------------------------------------------------------------------
// Part 3 - set midi program

if (content->currentMidiBank >= 0 and content->currentMidiProgram >= 0)
{
const uint32_t midiProgramCount = plugin->midiProgramCount();

for (uint32_t i=0; i < midiProgramCount; i++)
{
const MidiProgramData* const midiProgramData = plugin->midiProgramData(i);

if ((int32_t)midiProgramData->bank == content->currentMidiBank && (int32_t)midiProgramData->program == content->currentMidiProgram)
{
plugin->setMidiProgram(i, true, true, false, true);
break;
}
}
}

// ---------------------------------------------------------------------
// Part 4a - get plugin parameter symbols

struct ParamSymbol {
uint32_t index;
QString symbol;

ParamSymbol() {}

ParamSymbol(uint32_t index_, const char* symbol_)
: index(index_),
symbol(symbol_) {}
};

QVector<ParamSymbol> paramSymbols;

foreach (const CarlaStateParameter& parameter, content->parameters)
{
if (! parameter.symbol.isEmpty())
{
char strBuf[STR_MAX] = { 0 };
plugin->getParameterSymbol(parameter.index, strBuf);

if (strBuf[0] != 0)
{
ParamSymbol ps(parameter.index, strBuf);
paramSymbols.append(ps);
}
}
}

// ---------------------------------------------------------------------
// Part 4b - set parameter values (carefully)

const double sampleRate = engine->getSampleRate();

foreach (const CarlaStateParameter& parameter, content->parameters)
{
int32_t index = -1;

if (content->type == "LADSPA")
{
// Try to set by symbol, otherwise use index
if (! parameter.symbol.isEmpty())
{
bool breaked = false;

foreach (const ParamSymbol& ps, paramSymbols)
{
if (parameter.symbol == ps.symbol)
{
index = ps.index;
breaked = true;
break;
}
}

if (! breaked)
index = parameter.index;
}
else
index = parameter.index;
}
else if (content->type == "LV2")
{
// Symbol only
if (! parameter.symbol.isEmpty())
{
bool breaked = false;

foreach (const ParamSymbol& ps, paramSymbols)
{
if (parameter.symbol == ps.symbol)
{
index = ps.index;
breaked = true;
break;
}
}

if (! breaked)
qWarning("Failed to find LV2 parameter symbol for '%s')", parameter.symbol.toUtf8().constData());
}
else
qWarning("LV2 Plugin parameter '%s' has no symbol", parameter.name.toUtf8().constData());
}
else
{
// Index only
index = parameter.index;
}

// Now set parameter
if (index >= 0)
{
const ParameterData* const paramData = plugin->parameterData(index);
double value = parameter.value;

if (paramData->hints & PARAMETER_USES_SAMPLERATE)
value *= sampleRate;

plugin->setParameterValue(index, value, true, true, false);
plugin->setParameterMidiCC(index, parameter.midiCC, true, false);
plugin->setParameterMidiChannel(index, parameter.midiChannel-1, true, false);
}
else
qWarning("Could not set parameter data for '%s')", parameter.name.toUtf8().constData());
}

// ---------------------------------------------------------------------
// Part 5 - set chunk data

foreach (const CarlaStateCustomData& customData, content->customData)
{
if (customData.type == CUSTOM_DATA_CHUNK)
{
const char* const type = customData.type.toUtf8().constData();
const char* const key = customData.key.toUtf8().constData();
const char* const value = customData.value.toUtf8().constData();

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

if (! content->chunk.isEmpty())
plugin->setChunkData(content->chunk.toUtf8().constData());

qDebug("Loading plugin state now finished");
}

void guiClosed()
{
CARLA_ASSERT(engine);
@@ -352,16 +611,6 @@ public:
plugin->showGui(yesNo);
}

// ---------------------------------------------------------------------

static void callback(void* const ptr, CarlaBackend::CallbackType const action, const unsigned short, const int value1, const int value2, const double value3, const char* const valueStr)
{
CARLA_ASSERT(ptr);

if (CarlaPluginClient* const _this_ = (CarlaPluginClient*)ptr)
_this_->handleCallback(action, value1, value2, value3, valueStr);
}

// ---------------------------------------------------------------------
// processing

@@ -534,19 +783,119 @@ public:
}

// ---------------------------------------------------------------------
// callback

static void callback(void* const ptr, CarlaBackend::CallbackType const action, const unsigned short, const int value1, const int value2, const double value3, const char* const valueStr)
{
CARLA_ASSERT(ptr);

if (CarlaPluginClient* const _this_ = (CarlaPluginClient*)ptr)
_this_->handleCallback(action, value1, value2, value3, valueStr);
}

// ---------------------------------------------------------------------

protected:
int msgTimerGUI, msgTimerOSC;
int msgTimerGUI;
int msgTimerOSC;

bool needsResize;
int nextWidth;
int nextHeight;

CarlaBackend::CarlaEngine* engine;
CarlaBackend::CarlaPlugin* plugin;

std::set<int32_t> parametersToUpdate;

void handleCallback(const CarlaBackend::CallbackType action, const int value1, const int value2, const double value3, const char* const valueStr)
{
qDebug("CarlaPluginClient::handleCallback(%s, %i, %i, %g \"%s\")", CarlaBackend::CallbackType2Str(action), value1, value2, value3, valueStr);
CARLA_BACKEND_USE_NAMESPACE
qDebug("CarlaPluginClient::handleCallback(%s, %i, %i, %g \"%s\")", CallbackType2Str(action), value1, value2, value3, valueStr);

if (! engine)
return;

switch (action)
{
case CALLBACK_DEBUG:
break;

case CALLBACK_PARAMETER_VALUE_CHANGED:
parametersToUpdate.insert(value1);
break;

case CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED:
// todo, unused?
break;

case CALLBACK_PARAMETER_MIDI_CC_CHANGED:
// todo, unused?
break;

case CALLBACK_PROGRAM_CHANGED:
engine->osc_send_bridge_set_program(value1);
break;

case CALLBACK_MIDI_PROGRAM_CHANGED:
engine->osc_send_bridge_set_midi_program(value1);
break;

case CALLBACK_NOTE_ON:
// todo
break;

case CALLBACK_NOTE_OFF:
// todo
break;

case CALLBACK_SHOW_GUI:
if (value1 == 0)
{
CarlaBridgeToolkitPlugin* const plugToolkit = (CarlaBridgeToolkitPlugin*)m_toolkit;
plugToolkit->guiClosedCallback();
}
break;

case CALLBACK_RESIZE_GUI:
nextWidth = value1;
nextHeight = value2;
needsResize = true;
break;

case CALLBACK_UPDATE:
// todo
break;

case CALLBACK_RELOAD_INFO:
// todo
break;

case CALLBACK_RELOAD_PARAMETERS:
// todo
break;

case CALLBACK_RELOAD_PROGRAMS:
// todo
break;

case CALLBACK_RELOAD_ALL:
// todo
break;

case CALLBACK_NSM_ANNOUNCE:
case CALLBACK_NSM_OPEN1:
case CALLBACK_NSM_OPEN2:
case CALLBACK_NSM_SAVE:
break;

case CALLBACK_ERROR:
break;

case CALLBACK_QUIT:
m_toolkit->quit();
break;
}
}

void timerEvent(QTimerEvent* const event)
@@ -579,7 +928,6 @@ protected:

void CarlaBridgeToolkitPlugin::show()
{
qDebug("----------------------------------------------------------------------------------------------------------");
qDebug("CarlaBridgeToolkitPlugin::show()");
CARLA_ASSERT(gui);



+ 9
- 2
c++/carla-bridge/qtcreator/carla-bridge-plugin.pro View File

@@ -1,9 +1,9 @@
# QtCreator project file

contains(QT_VERSION, ^5.*) {
QT = core widgets
QT = core widgets xml
} else {
QT = core gui
QT = core gui xml
}

CONFIG = debug link_pkgconfig qt warn_on
@@ -25,6 +25,13 @@ HEADERS = \
../carla_bridge_osc.hpp \
../carla_bridge_toolkit.hpp \

# carla
SOURCES += \
../../carla/Shared.cpp

HEADERS += \
../../carla/Shared.hpp

# carla-engine
SOURCES += \
../../carla-engine/carla_engine.cpp \


+ 257
- 0
c++/carla/Shared.cpp View File

@@ -0,0 +1,257 @@
/*
* Carla (frontend)
* Copyright (C) 2012 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 published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "Shared.hpp"

//#define __STDC_LIMIT_MACROS
//#include <cstdint>

CARLA_BACKEND_USE_NAMESPACE

// ------------------------------------------------------------------------------------------------
// Carla Host object

CarlaHostObject Carla;

// ------------------------------------------------------------------------------------------------------------
// Carla XML helpers

const CarlaSaveState* getSaveStateDictFromXML(const QDomNode& xmlNode)
{
static CarlaSaveState saveState;
saveState.reset();

QDomNode node(xmlNode.firstChild());

while (! node.isNull())
{
// ------------------------------------------------------
// Info

if (node.toElement().tagName() == "Info")
{
QDomNode xmlInfo(node.toElement().firstChild());

while (! xmlInfo.isNull())
{
const QString tag = xmlInfo.toElement().tagName();
const QString text = xmlInfo.toElement().text(); //.strip();

if (tag == "Type")
saveState.type = text;
else if (tag == "Name")
saveState.name = xmlSafeString(text, false);
else if (tag == "Label" || tag == "URI")
saveState.label = xmlSafeString(text, false);
else if (tag == "Binary")
saveState.binary = xmlSafeString(text, false);
else if (tag == "UniqueID")
{
bool ok;
long uniqueID = text.toLong(&ok);
if (ok) saveState.uniqueID = uniqueID;
}

xmlInfo = xmlInfo.nextSibling();
}
}

// ------------------------------------------------------
// Data

else if (node.toElement().tagName() == "Data")
{
QDomNode xmlData(node.toElement().firstChild());

while (! xmlData.isNull())
{
const QString tag = xmlData.toElement().tagName();
const QString text = xmlData.toElement().text(); //.strip();

// ----------------------------------------------
// Internal Data

if (tag == "Active")
{
saveState.active = bool(text == "Yes");
}
else if (tag == "DryWet")
{
bool ok;
double value = text.toDouble(&ok);
if (ok) saveState.dryWet = value;
}
else if (tag == "Volume")
{
bool ok;
double value = text.toDouble(&ok);
if (ok) saveState.volume = value;
}
else if (tag == "Balance-Left")
{
bool ok;
double value = text.toDouble(&ok);
if (ok) saveState.balanceLeft = value;
}
else if (tag == "Balance-Right")
{
bool ok;
double value = text.toDouble(&ok);
if (ok) saveState.balanceRight = value;
}

// ----------------------------------------------
// Program (current)

else if (tag == "CurrentProgramIndex")
{
bool ok;
int value = text.toInt(&ok);
if (ok) saveState.currentProgramIndex = value;
}
else if (tag == "CurrentProgramName")
{
saveState.currentProgramName = xmlSafeString(text, false);
}

// ----------------------------------------------
// Midi Program (current)

else if (tag == "CurrentMidiBank")
{
bool ok;
int value = text.toInt(&ok);
if (ok) saveState.currentMidiBank = value;
}
else if (tag == "CurrentMidiProgram")
{
bool ok;
int value = text.toInt(&ok);
if (ok) saveState.currentMidiProgram = value;
}

// ----------------------------------------------
// Parameters

else if (tag == "Parameter")
{
CarlaStateParameter stateParameter;

QDomNode xmlSubData(xmlData.toElement().firstChild());

while (! xmlSubData.isNull())
{
const QString pTag = xmlSubData.toElement().tagName();
const QString pText = xmlSubData.toElement().text(); //.strip();

if (pTag == "index")
{
bool ok;
uint index = pText.toUInt(&ok);
if (ok) stateParameter.index = index;
}
else if (pTag == "name")
{
stateParameter.name = xmlSafeString(pText, false);
}
else if (pTag == "symbol")
{
stateParameter.symbol = xmlSafeString(pText, false);
}
else if (pTag == "value")
{
bool ok;
double value = pText.toDouble(&ok);
if (ok) stateParameter.value = value;
}
else if (pTag == "midiChannel")
{
bool ok;
uint channel = pText.toUInt(&ok);
if (ok && channel < 16)
stateParameter.midiChannel = channel;
}
else if (pTag == "midiCC")
{
bool ok;
int cc = pText.toInt(&ok);
if (ok && cc < INT16_MAX)
stateParameter.midiCC = cc;
}

xmlSubData = xmlSubData.nextSibling();
}

saveState.parameters.append(stateParameter);
}

// ----------------------------------------------
// Custom Data

else if (tag == "CustomData")
{
CarlaStateCustomData stateCustomData;

QDomNode xmlSubData(xmlData.toElement().firstChild());

while (! xmlSubData.isNull())
{
const QString cTag = xmlSubData.toElement().tagName();
const QString cText = xmlSubData.toElement().text(); //.strip();

if (cTag == "type")
stateCustomData.type = xmlSafeString(cText, false);
else if (cTag == "key")
stateCustomData.key = xmlSafeString(cText, false);
else if (cTag == "value")
stateCustomData.value = xmlSafeString(cText, false);

xmlSubData = xmlSubData.nextSibling();
}

saveState.customData.append(stateCustomData);
}

// ----------------------------------------------
// Chunk

else if (tag == "Chunk")
{
saveState.chunk = xmlSafeString(text, false);
}

// ----------------------------------------------

xmlData = xmlData.nextSibling();
}
}

// ------------------------------------------------------

node = node.nextSibling();
}

return &saveState;
}

QString xmlSafeString(QString string, const bool toXml)
{
if (toXml)
return string.replace("&", "&amp;").replace("<","&lt;").replace(">","&gt;").replace("'","&apos;").replace("\"","&quot;");
else
return string.replace("&amp;", "&").replace("&lt;","<").replace("&gt;",">").replace("&apos;","'").replace("&quot;","\"");
}

+ 151
- 0
c++/carla/Shared.hpp View File

@@ -0,0 +1,151 @@
/*
* Carla (frontend)
* Copyright (C) 2012 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 published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef SHARED_HPP
#define SHARED_HPP

#include "carla_backend.hpp"

#include <QtCore/QString>
#include <QtCore/QVector>
#include <QtXml/QDomNode>

CARLA_BACKEND_USE_NAMESPACE

#define VERSION "0.5.0"

// ------------------------------------------------------------------------------------------------
// Carla Host object

struct CarlaHostObject {
void* host;
void* gui;
bool isControl;
ProcessMode processMode;
unsigned int maxParameters;

CarlaHostObject()
: host(nullptr),
gui(nullptr),
isControl(false),
processMode(PROCESS_MODE_CONTINUOUS_RACK),
maxParameters(MAX_PARAMETERS) {}
};

extern CarlaHostObject Carla;

// ------------------------------------------------------------------------------------------------
// Carla GUI stuff

#define ICON_STATE_NULL 0
#define ICON_STATE_WAIT 1
#define ICON_STATE_OFF 2
#define ICON_STATE_ON 3

#define PALETTE_COLOR_NONE 0
#define PALETTE_COLOR_WHITE 1
#define PALETTE_COLOR_RED 2
#define PALETTE_COLOR_GREEN 3
#define PALETTE_COLOR_BLUE 4
#define PALETTE_COLOR_YELLOW 5
#define PALETTE_COLOR_ORANGE 6
#define PALETTE_COLOR_BROWN 7
#define PALETTE_COLOR_PINK 8

struct CarlaStateParameter {
uint32_t index;
QString name;
QString symbol;
double value;
uint8_t midiChannel;
int16_t midiCC;

CarlaStateParameter()
: index(0),
value(0.0),
midiChannel(1),
midiCC(-1) {}
};

struct CarlaStateCustomData {
QString type;
QString key;
QString value;

CarlaStateCustomData() {}
};

struct CarlaSaveState {
QString type;
QString name;
QString label;
QString binary;
long uniqueID;
bool active;
double dryWet;
double volume;
double balanceLeft;
double balanceRight;
QVector<CarlaStateParameter> parameters;
int32_t currentProgramIndex;
QString currentProgramName;
int32_t currentMidiBank;
int32_t currentMidiProgram;
QVector<CarlaStateCustomData> customData;
QString chunk;

CarlaSaveState()
: uniqueID(0),
active(false),
dryWet(1.0),
volume(1.0),
balanceLeft(-1.0),
balanceRight(1.0),
currentProgramIndex(-1),
currentMidiBank(-1),
currentMidiProgram(-1) {}

void reset()
{
type.clear();
name.clear();
label.clear();
binary.clear();
uniqueID = 0;
active = false;
dryWet = 1.0;
volume = 1.0;
balanceLeft = -1.0;
balanceRight = 1.0;
parameters.clear();
currentProgramIndex = -1;
currentProgramName.clear();
currentMidiBank = -1;
currentMidiProgram = -1;
customData.clear();
chunk.clear();
}
};

// ------------------------------------------------------------------------------------------------------------
// Carla XML helpers

const CarlaSaveState* getSaveStateDictFromXML(const QDomNode& xmlNode);

QString xmlSafeString(QString string, const bool toXml);

#endif // SHARED_HPP

+ 4
- 0
doc/TODO View File

@@ -12,6 +12,10 @@ GUI:
-------------------
- APPS -

Cadence:
- add freq info to systray tooltip
- add freq Hz change

Claudia:
- Cleanup DB
- Handle sample-rate changes in JACK (made possible by switch-master)


+ 7
- 4
src/shared_carla.py View File

@@ -267,6 +267,9 @@ CarlaSaveState = {
'Chunk': None
}

# ------------------------------------------------------------------------------------------------------------
# Carla XML helpers

def getSaveStateDictFromXML(xmlNode):
saveState = deepcopy(CarlaSaveState)

@@ -378,7 +381,7 @@ def getSaveStateDictFromXML(xmlNode):
cText = xmlSubData.toElement().text().strip()

if cTag == "type":
stateCustomData['type'] = cText
stateCustomData['type'] = xmlSafeString(cText, False)
elif cTag == "key":
stateCustomData['key'] = xmlSafeString(cText, False)
elif cTag == "value":
@@ -1751,7 +1754,7 @@ class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget):
# Part 1 - set custom data (except binary/chunks)

for customData in content['CustomData']:
if customData['type'] not in (CUSTOM_DATA_BINARY, CUSTOM_DATA_CHUNK):
if customData['type'] != CUSTOM_DATA_CHUNK:
Carla.host.set_custom_data(self.m_pluginId, customData['type'], customData['key'], customData['value'])

# ---------------------------------------------------------------------
@@ -1763,7 +1766,7 @@ class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget):
programCount = Carla.host.get_program_count(self.m_pluginId)
testProgramName = cString(Carla.host.get_program_name(self.m_pluginId, content['CurrentProgramIndex']))

# Program index and name matches
# Program name matches
if content['CurrentProgramName'] == testProgramName:
programId = content['CurrentProgramIndex']

@@ -1863,7 +1866,7 @@ class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget):
# Part 5 - set chunk data

for customData in content['CustomData']:
if customData['type'] in (CUSTOM_DATA_BINARY, CUSTOM_DATA_CHUNK):
if customData['type'] == CUSTOM_DATA_CHUNK:
Carla.host.set_custom_data(self.m_pluginId, customData['type'], customData['key'], customData['value'])

if content['Chunk']:


Loading…
Cancel
Save