Browse Source

Implement file load/save via juce; Misc cleanup/fixing

tags/1.9.4
falkTX 12 years ago
parent
commit
87c9df5d1b
17 changed files with 725 additions and 358 deletions
  1. +1
    -1
      source/backend/CarlaBackend.hpp
  2. +70
    -80
      source/backend/engine/CarlaEngine.cpp
  3. +5
    -0
      source/backend/engine/CarlaEngineJack.cpp
  4. +2
    -4
      source/backend/plugin/CarlaPlugin.cpp
  5. +0
    -10
      source/carla-mini
  6. +367
    -0
      source/carla-plugin
  7. +74
    -7
      source/carla_backend.py
  8. +0
    -93
      source/carla_control.py
  9. +3
    -1
      source/carla_database.py
  10. +157
    -133
      source/carla_host.py
  11. +25
    -25
      source/carla_patchbay.py
  12. +2
    -2
      source/carla_rack.py
  13. +8
    -0
      source/carla_settings.py
  14. +4
    -1
      source/carla_shared.py
  15. +3
    -1
      source/carla_widgets.py
  16. +0
    -0
      source/externalui.py
  17. +4
    -0
      source/utils/CarlaBackendUtils.hpp

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

@@ -691,7 +691,7 @@ struct ParameterData {
ParameterType type;
int32_t index;
int32_t rindex;
uint32_t hints;
unsigned int hints;
uint8_t midiChannel;
int16_t midiCC;



+ 70
- 80
source/backend/engine/CarlaEngine.cpp View File

@@ -381,7 +381,12 @@ const char** CarlaEngine::getDriverDeviceNames(const unsigned int index)
carla_debug("CarlaEngine::getDriverDeviceNames(%i)", index);

if (index == 0)
return nullptr;
{
//static const char* const strOff = "Auto-connect OFF";
//static const char* const strOn = "Auto-connect ON";
static const char* ret[3] = { "Auto-connect OFF", "Auto-connect ON", nullptr };
return ret;
}

#ifndef BUILD_BRIDGE
const unsigned int rtAudioIndex(index-1);
@@ -1057,29 +1062,18 @@ bool CarlaEngine::loadFilename(const char* const filename)
CARLA_ASSERT(filename != nullptr);
carla_debug("CarlaEngine::loadFilename(\"%s\")", filename);

#if 0
QFileInfo fileInfo(filename);
using namespace juce;

if (! fileInfo.exists())
{
setLastError("File does not exist");
return false;
}

if (! fileInfo.isFile())
{
setLastError("Not a file");
return false;
}
File file(filename);

if (! fileInfo.isReadable())
if (! file.existsAsFile())
{
setLastError("File is not readable");
setLastError("File does not exist");
return false;
}

CarlaString baseName(fileInfo.baseName().toUtf8().constData());
CarlaString extension(fileInfo.suffix().toLower().toUtf8().constData());
CarlaString baseName(file.getFileNameWithoutExtension().toRawUTF8());
CarlaString extension(file.getFileExtension().toRawUTF8());

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

@@ -1175,7 +1169,6 @@ bool CarlaEngine::loadFilename(const char* const filename)
}

// -------------------------------------------------------------------
#endif

setLastError("Unknown file extension");
return false;
@@ -1200,71 +1193,68 @@ bool CarlaEngine::loadProject(const char* const filename)
CARLA_ASSERT(filename != nullptr);
carla_debug("CarlaEngine::loadProject(\"%s\")", filename);

#if 0
QFile file(filename);

if (! file.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
using namespace juce;

QDomDocument xml;
xml.setContent(file.readAll());
file.close();
File file(filename);

QDomNode xmlNode(xml.documentElement());
XmlDocument xml(file);

if (xmlNode.toElement().tagName() != "CARLA-PROJECT" && xmlNode.toElement().tagName() != "CARLA-PRESET")
if (XmlElement* const xmlCheck = xml.getDocumentElement(true))
{
setLastError("Not a valid Carla project or preset file");
return false;
}
const String& tagNameTest(xmlCheck->getTagName());
const bool isPreset(tagNameTest.equalsIgnoreCase("carla-preset"));

const bool isPreset(xmlNode.toElement().tagName() == "CARLA-PRESET");
if (tagNameTest.equalsIgnoreCase("carla-project") || isPreset)
{
if (XmlElement* const xmlElem = xml.getDocumentElement(false))
{
for (XmlElement* subElem = xmlElem->getFirstChildElement(); subElem != nullptr; subElem = subElem->getNextElement())
{
if (isPreset || subElem->getTagName().equalsIgnoreCase("Plugin"))
{
SaveState saveState;
fillSaveStateFromXmlElement(saveState, isPreset ? xmlElem : subElem);

QDomNode node(xmlNode.firstChild());
CARLA_SAFE_ASSERT_CONTINUE(saveState.type != nullptr);

while (! node.isNull())
{
if (isPreset || node.toElement().tagName() == "Plugin")
{
SaveState saveState;
fillSaveStateFromXmlNode(saveState, isPreset ? xmlNode : node);
const void* extraStuff = nullptr;

CARLA_ASSERT(saveState.type != nullptr);
if (std::strcmp(saveState.type, "SF2") == 0)
{
const char* const use16OutsSuffix = " (16 outs)";

if (saveState.type == nullptr)
continue;
if (charEndsWith(saveState.label, use16OutsSuffix))
extraStuff = (void*)0x1; // non-null
}

const void* extraStuff = nullptr;
// TODO - proper find&load plugins

if (std::strcmp(saveState.type, "DSSI") == 0)
{
extraStuff = findDSSIGUI(saveState.binary, saveState.label);
}
else if (std::strcmp(saveState.type, "SF2") == 0)
{
const char use16OutsSuffix[] = " (16 outs)";
if (addPlugin(getPluginTypeFromString(saveState.type), saveState.binary, saveState.name, saveState.label, extraStuff))
{
if (CarlaPlugin* plugin = getPlugin(pData->curPluginCount-1))
plugin->loadSaveState(saveState);
}
}

if (charEndsWith(saveState.label, use16OutsSuffix))
extraStuff = (void*)0x1; // non-null
}
if (isPreset)
break;
}

// TODO - proper find&load plugins
if (addPlugin(getPluginTypeFromString(saveState.type), saveState.binary, saveState.name, saveState.label, extraStuff))
{
if (CarlaPlugin* plugin = getPlugin(pData->curPluginCount-1))
plugin->loadSaveState(saveState);
delete xmlElem;
delete xmlCheck;
return true;
}
else
setLastError("Failed to parse file");
}
else
setLastError("Not a valid Carla project or preset file");

if (isPreset)
break;

node = node.nextSibling();
delete xmlCheck;
return false;
}

return true;
#endif
setLastError("Not implemented yet");
setLastError("Not a valid file");
return false;
}

@@ -1273,16 +1263,14 @@ bool CarlaEngine::saveProject(const char* const filename)
CARLA_ASSERT(filename != nullptr);
carla_debug("CarlaEngine::saveProject(\"%s\")", filename);

#if 0
QFile file(filename);
using namespace juce;

if (! file.open(QIODevice::WriteOnly | QIODevice::Text))
return false;
File file(filename);

QTextStream out(&file);
MemoryOutputStream out;
out << "<?xml version='1.0' encoding='UTF-8'?>\n";
out << "<!DOCTYPE CARLA-PROJECT>\n";
out << "<CARLA-PROJECT VERSION='1.0'>\n";
out << "<CARLA-PROJECT VERSION='2.0'>\n";

bool firstPlugin = true;
char strBuf[STR_MAX+1];
@@ -1296,12 +1284,18 @@ bool CarlaEngine::saveProject(const char* const filename)
if (! firstPlugin)
out << "\n";

strBuf[0] = '\0';

plugin->getRealName(strBuf);

if (*strBuf != 0)
out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true));
if (strBuf[0] != '\0')
{
out << " <!-- ";
out << xmlSafeString(strBuf, true);
out << " -->\n";
}

QString content;
String content;
fillXmlStringFromSaveState(content, plugin->getSaveState());

out << " <Plugin>\n";
@@ -1314,11 +1308,7 @@ bool CarlaEngine::saveProject(const char* const filename)

out << "</CARLA-PROJECT>\n";

file.close();
return true;
#endif
setLastError("Not implemented yet");
return false;
return file.replaceWithData(out.getData(), out.getDataSize());
}

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


+ 5
- 0
source/backend/engine/CarlaEngineJack.cpp View File

@@ -227,6 +227,11 @@ public:
CARLA_SAFE_ASSERT_RETURN(fIsInput, kFallbackJackEngineEvent);
CARLA_SAFE_ASSERT_RETURN(fJackBuffer != nullptr, kFallbackJackEngineEvent);

return getEventUnchecked(index);
}

const EngineEvent& getEventUnchecked(const uint32_t index) override
{
jack_midi_event_t jackEvent;
carla_zeroStruct<jack_midi_event_t>(jackEvent);



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

@@ -829,16 +829,14 @@ bool CarlaPlugin::saveStateToFile(const char* const filename)
String content;
fillXmlStringFromSaveState(content, getSaveState());

String out;
MemoryOutputStream out;
out << "<?xml version='1.0' encoding='UTF-8'?>\n";
out << "<!DOCTYPE CARLA-PRESET>\n";
out << "<CARLA-PRESET VERSION='2.0'>\n";
out << content;
out << "</CARLA-PRESET>\n";

carla_stdout("TESTING, FULL OUT FILE:\n%s", out.toRawUTF8());

return file.replaceWithText(out);
return file.replaceWithData(out.getData(), out.getDataSize());
}

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


+ 0
- 10
source/carla-mini View File

@@ -16,16 +16,6 @@
#
# For a full copy of the GNU General Public License see the GPL.txt file

# ------------------------------------------------------------------------------------------------------------
# Imports (Global)

try:
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication
except:
from PyQt4.QtCore import QTimer
from PyQt4.QtGui import QApplication

# ------------------------------------------------------------------------------------------------------------
# Imports (Custom Stuff)



+ 367
- 0
source/carla-plugin View File

@@ -0,0 +1,367 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Carla plugin host (plugin UI)
# Copyright (C) 2013 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 GPL.txt file

# ------------------------------------------------------------------------------------------------------------
# Imports (Custom Stuff)

from carla_host import *
from externalui import ExternalUI

# ------------------------------------------------------------------------------------------------------------
# Host Plugin object

class PluginHost(object):
def __init__(self):
object.__init__(self)

self.fParent = None

self.fBufferSize = 0
self.fSampleRate = 0.0
self.fLastError = ""
self.fSupportedFileTypes = ""

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

def get_engine_driver_count(self):
return 0

def get_supported_file_types(self):
return self.fSupportedFileTypes

def engine_init(self, driverName, clientName):
return True

def engine_close(self):
return True

def is_engine_running(self):
return True

def set_engine_about_to_close(self):
pass

def set_engine_callback(self, func):
pass

def load_filename(self, filename):
self.fParent.send(["load_filename", filename])
return True

def load_project(self, filename):
self.fParent.send(["load_project", filename])
return True

def save_project(self, filename):
self.fParent.send(["save_project", filename])
return True

def patchbay_connect(self, portIdA, portIdB):
self.fParent.send(["patchbay_connect", portIdA, portIdB])
return True

def patchbay_disconnect(self, connectionId):
self.fParent.send(["patchbay_disconnect", connectionId])
return True

def patchbay_refresh(self):
self.fParent.send(["patchbay_refresh"])

def add_plugin(self, btype, ptype, filename, name, label, extraStuff):
self.fParent.send(["add_plugin", btype, ptype, filename, name, label])
return True

def remove_plugin(self, pluginId):
self.fParent.send(["remove_plugin", pluginId])
return True

def remove_all_plugins(self):
self.fParent.send(["remove_all_plugins"])

def rename_plugin(self, pluginId, newName):
self.fParent.send(["rename_plugin", pluginId, newName])
return True

def clone_plugin(self, pluginId):
self.fParent.send(["clone_plugin", pluginId])
return True

def replace_plugin(self, pluginId):
self.fParent.send(["replace_plugin", pluginId])
return True

def switch_plugins(self, pluginIdA, pluginIdB):
self.fParent.send(["switch_plugins", pluginIdA, pluginIdB])
return True

def load_plugin_state(self, pluginId, filename):
self.fParent.send(["load_plugin_state", pluginId, filename])
return True

def save_plugin_state(self, pluginId, filename):
self.fParent.send(["save_plugin_state", pluginId, filename])
return True

#def get_plugin_info(self, pluginId):
#return structToDict(self.lib.carla_get_plugin_info(pluginId).contents)

#def get_audio_port_count_info(self, pluginId):
#return structToDict(self.lib.carla_get_audio_port_count_info(pluginId).contents)

#def get_midi_port_count_info(self, pluginId):
#return structToDict(self.lib.carla_get_midi_port_count_info(pluginId).contents)

#def get_parameter_count_info(self, pluginId):
#return structToDict(self.lib.carla_get_parameter_count_info(pluginId).contents)

#def get_parameter_info(self, pluginId, parameterId):
#return structToDict(self.lib.carla_get_parameter_info(pluginId, parameterId).contents)

#def get_parameter_scalepoint_info(self, pluginId, parameterId, scalePointId):
#return structToDict(self.lib.carla_get_parameter_scalepoint_info(pluginId, parameterId, scalePointId).contents)

#def get_parameter_data(self, pluginId, parameterId):
#return structToDict(self.lib.carla_get_parameter_data(pluginId, parameterId).contents)

#def get_parameter_ranges(self, pluginId, parameterId):
#return structToDict(self.lib.carla_get_parameter_ranges(pluginId, parameterId).contents)

#def get_midi_program_data(self, pluginId, midiProgramId):
#return structToDict(self.lib.carla_get_midi_program_data(pluginId, midiProgramId).contents)

#def get_custom_data(self, pluginId, customDataId):
#return structToDict(self.lib.carla_get_custom_data(pluginId, customDataId).contents)

#def get_chunk_data(self, pluginId):
#return self.lib.carla_get_chunk_data(pluginId)

#def get_parameter_count(self, pluginId):
#return self.lib.carla_get_parameter_count(pluginId)

#def get_program_count(self, pluginId):
#return self.lib.carla_get_program_count(pluginId)

#def get_midi_program_count(self, pluginId):
#return self.lib.carla_get_midi_program_count(pluginId)

#def get_custom_data_count(self, pluginId):
#return self.lib.carla_get_custom_data_count(pluginId)

#def get_parameter_text(self, pluginId, parameterId):
#return self.lib.carla_get_parameter_text(pluginId, parameterId)

#def get_program_name(self, pluginId, programId):
#return self.lib.carla_get_program_name(pluginId, programId)

#def get_midi_program_name(self, pluginId, midiProgramId):
#return self.lib.carla_get_midi_program_name(pluginId, midiProgramId)

#def get_real_plugin_name(self, pluginId):
#return self.lib.carla_get_real_plugin_name(pluginId)

#def get_current_program_index(self, pluginId):
#return self.lib.carla_get_current_program_index(pluginId)

#def get_current_midi_program_index(self, pluginId):
#return self.lib.carla_get_current_midi_program_index(pluginId)

#def get_default_parameter_value(self, pluginId, parameterId):
#return self.lib.carla_get_default_parameter_value(pluginId, parameterId)

#def get_current_parameter_value(self, pluginId, parameterId):
#return self.lib.carla_get_current_parameter_value(pluginId, parameterId)

#def get_input_peak_value(self, pluginId, portId):
#return self.lib.carla_get_input_peak_value(pluginId, portId)

#def get_output_peak_value(self, pluginId, portId):
#return self.lib.carla_get_output_peak_value(pluginId, portId)

def set_option(self, pluginId, option, yesNo):
self.fParent.send(["set_option", pluginId, option, yesNo])

def set_active(self, pluginId, onOff):
self.fParent.send(["set_active", pluginId, onOff])

def set_drywet(self, pluginId, value):
self.fParent.send(["set_drywet", pluginId, value])

def set_volume(self, pluginId, value):
self.fParent.send(["set_volume", pluginId, value])

def set_balance_left(self, pluginId, value):
self.fParent.send(["set_balance_left", pluginId, value])

def set_balance_right(self, pluginId, value):
self.fParent.send(["set_balance_right", pluginId, value])

def set_panning(self, pluginId, value):
self.fParent.send(["set_panning", pluginId, value])

def set_ctrl_channel(self, pluginId, channel):
self.fParent.send(["set_ctrl_channel", pluginId, channel])

def set_parameter_value(self, pluginId, parameterId, value):
self.fParent.send(["set_parameter_value", pluginId, parameterId, value])

def set_parameter_midi_cc(self, pluginId, parameterId, cc):
self.fParent.send(["set_parameter_midi_cc", pluginId, parameterId, cc])

def set_parameter_midi_channel(self, pluginId, parameterId, channel):
self.fParent.send(["set_parameter_midi_channel", pluginId, parameterId, channel])

def set_program(self, pluginId, programId):
self.fParent.send(["set_program", pluginId, programId])

def set_midi_program(self, pluginId, midiProgramId):
self.fParent.send(["set_midi_program", pluginId, midiProgramId])

def set_custom_data(self, pluginId, type_, key, value):
self.fParent.send(["set_custom_data", pluginId, type_, key, value])

def set_chunk_data(self, pluginId, chunkData):
self.fParent.send(["set_chunk_data", pluginId, chunkData])

def prepare_for_save(self, pluginId):
self.fParent.send(["prepare_for_save", pluginId])

def send_midi_note(self, pluginId, channel, note, velocity):
self.fParent.send(["send_midi_note", pluginId, channel, note, velocity])

def show_gui(self, pluginId, yesNo):
self.fParent.send(["show_gui", pluginId, yesNo])

def get_last_error(self):
return self.fLastError

def get_buffer_size(self):
return self.fBufferSize

def get_sample_rate(self):
return self.fSampleRate

# ------------------------------------------------------------------------------------------------------------
# Init plugin

def initPlugin():
Carla.host = PluginHost()

# ------------------------------------------------------------------------------------------------------------
# Main Window

class CarlaMiniW(HostWindow, ExternalUI):
def __init__(self):
HostWindow.__init__(self, None)
ExternalUI.__init__(self)

if Carla.host is not None:
Carla.host.fParent = None
Carla.host.fSampleRate = self.d_getSampleRate()

if False:
from carla_patchbay import CarlaPatchbayW
self.fContainer = CarlaPatchbayW(self)
else:
from carla_rack import CarlaRackW
self.fContainer = CarlaRackW(self)

self.setCentralWidget(self.fContainer)
self.setWindowTitle(self.fUiName)

self.fIdleTimer = self.startTimer(50)

self.showUiIfTesting()

# -------------------------------------------------------------------
# ExternalUI Callbacks

def d_uiShow(self):
self.show()

def d_uiHide(self):
self.hide()

def d_uiQuit(self):
self.close()
app.quit()

def d_uiTitleChanged(self, uiTitle):
self.setWindowTitle(uiTitle)

# -------------------------------------------------------------------
# Qt events

def timerEvent(self, event):
if event.timerId() == self.fIdleTimer:
if not self.idleExternalUI():
self.d_uiQuit()

QWidget.timerEvent(self, event)

def closeEvent(self, event):
self.closeExternalUI()
HostWindow.closeEvent(self, event)

# ------------------------------------------------------------------------------------------------------------
# Main

if __name__ == '__main__':
# -------------------------------------------------------------
# Setup

Carla.isControl = False
Carla.isLocal = False
Carla.isPlugin = True

# -------------------------------------------------------------
# App initialization

app = QApplication(sys.argv)
app.setApplicationName("Carla")
app.setApplicationVersion(VERSION)
app.setOrganizationName("falkTX")
app.setWindowIcon(QIcon(":/scalable/carla.svg"))

# -------------------------------------------------------------
# Set-up custom signal handling

setUpSignals()

# -------------------------------------------------------------
# Read CLI args

argv = app.arguments()
argc = len(argv)

if argc > 1:
pass

# -------------------------------------------------------------
# Init plugin backend

initPlugin()

# -------------------------------------------------------------
# Create GUI

Carla.gui = CarlaMiniW()

# -------------------------------------------------------------
# App-Loop

sys.exit(app.exec_())

+ 74
- 7
source/carla_backend.py View File

@@ -89,7 +89,7 @@ def structToDict(struct):

MAX_DEFAULT_PLUGINS = 99
MAX_RACK_PLUGINS = 16
MAX_PATCHBAY_PLUGINS = 999
MAX_PATCHBAY_PLUGINS = 255
MAX_DEFAULT_PARAMETERS = 200

# Plugin Hints
@@ -162,13 +162,13 @@ PLUGIN_SFZ = 10
# Plugin Category
PLUGIN_CATEGORY_NONE = 0
PLUGIN_CATEGORY_SYNTH = 1
PLUGIN_CATEGORY_DELAY = 2 # also Reverb
PLUGIN_CATEGORY_DELAY = 2
PLUGIN_CATEGORY_EQ = 3
PLUGIN_CATEGORY_FILTER = 4
PLUGIN_CATEGORY_DYNAMICS = 5 # Amplifier, Compressor, Gate
PLUGIN_CATEGORY_MODULATOR = 6 # Chorus, Flanger, Phaser
PLUGIN_CATEGORY_UTILITY = 7 # Analyzer, Converter, Mixer
PLUGIN_CATEGORY_OTHER = 8 # used to check if a plugin has a category
PLUGIN_CATEGORY_DYNAMICS = 5
PLUGIN_CATEGORY_MODULATOR = 6
PLUGIN_CATEGORY_UTILITY = 7
PLUGIN_CATEGORY_OTHER = 8

# Parameter Type
PARAMETER_UNKNOWN = 0
@@ -304,7 +304,7 @@ class ParameterData(Structure):
("type", c_enum),
("index", c_int32),
("rindex", c_int32),
("hints", c_uint32),
("hints", c_uint),
("midiChannel", c_uint8),
("midiCC", c_int16)
]
@@ -400,6 +400,73 @@ class CarlaTransportInfo(Structure):
("bpm", c_double)
]

# ------------------------------------------------------------------------------------------------------------
# Python object dicts compatible with ctypes struct

PyParameterData = {
'type': PARAMETER_NULL,
'index': 0,
'rindex': -1,
'hints': 0x0,
'midiChannel': 0,
'midiCC': -1
}

PyParameterRanges = {
'def': 0.0,
'min': 0.0,
'max': 1.0,
'step': 0.0,
'stepSmall': 0.0,
'stepLarge': 0.0
}

PyMidiProgramData = {
'bank': 0,
'program': 0,
'name': None
}

PyCustomData = {
'type': None,
'key': None,
'value': None
}

PyCarlaPluginInfo = {
'type': PLUGIN_NONE,
'category': PLUGIN_CATEGORY_NONE,
'hints': 0x0,
'optionsAvailable': 0x0,
'optionsEnabled': 0x0,
'binary': None,
'name': None,
'label': None,
'maker': None,
'copyright': None,
'iconName': None,
'uniqueId': 0,
'latency': 0
}

PyCarlaPortCountInfo = {
'ins': 0,
'outs': 0,
'total': 0
}

PyCarlaParameterInfo = {
'name': None,
'symbol': None,
'unit': None,
'scalePointCount': 0,
}

PyCarlaScalePointInfo = {
'value': 0.0,
'label': None
}

# ------------------------------------------------------------------------------------------------------------
# Host Python object (Control/Standalone)



+ 0
- 93
source/carla_control.py View File

@@ -39,99 +39,6 @@ lo_targetName = ""
Carla.isControl = True
Carla.isLocal = False

# ------------------------------------------------------------------------------------------------------------
# Python Object dicts compatible to carla-backend struct ctypes

ParameterData = {
'type': PARAMETER_NULL,
'index': 0,
'rindex': -1,
'hints': 0x0,
'midiChannel': 0,
'midiCC': -1
}

ParameterRanges = {
'def': 0.0,
'min': 0.0,
'max': 1.0,
'step': 0.0,
'stepSmall': 0.0,
'stepLarge': 0.0
}

MidiProgramData = {
'bank': 0,
'program': 0,
'name': None
}

CustomData = {
'type': CUSTOM_DATA_INVALID,
'key': None,
'value': None
}

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

CarlaPluginInfo = {
'type': PLUGIN_NONE,
'category': PLUGIN_CATEGORY_NONE,
'hints': 0x0,
'optionsAvailable': 0x0,
'optionsEnabled': 0x0,
'binary': None,
'name': None,
'label': None,
'maker': None,
'copyright': None,
'iconName': None,
'uniqueId': 0,
'latency': 0
}

CarlaNativePluginInfo = {
'category': PLUGIN_CATEGORY_NONE,
'hints': 0x0,
'audioIns': 0,
'audioOuts': 0,
'midiIns': 0,
'midiOuts': 0,
'parameterIns': 0,
'parameterOuts': 0,
'name': None,
'label': None,
'maker': None,
'copyright': None
}

CarlaPortCountInfo = {
'ins': 0,
'outs': 0,
'total': 0
}

CarlaParameterInfo = {
'name': None,
'symbol': None,
'unit': None,
'scalePointCount': 0,
}

CarlaScalePointInfo = {
'value': 0.0,
'label': None
}

CarlaTransportInfo = {
'playing': False,
'frame': 0,
'bar': 0,
'beat': 0,
'tick': 0,
'bpm': 0.0
}

# ------------------------------------------------------------------------------------------------------------
# Helper class



+ 3
- 1
source/carla_database.py View File

@@ -1442,7 +1442,9 @@ class PluginDatabaseW(QDialog):
for plugins in internalPlugins:
internalCount += len(plugins)

if Carla.host is not None and internalCount != Carla.host.get_internal_plugin_count():
canRefreshInternals = not (Carla.isControl or Carla.isPlugin or Carla.host is None)

if canRefreshInternals and internalCount != Carla.host.get_internal_plugin_count():
internalCount = Carla.host.get_internal_plugin_count()
internalPlugins = []



+ 157
- 133
source/carla_host.py View File

@@ -192,12 +192,21 @@ class HostWindow(QMainWindow):
# -------------------------------------------------------------
# Set up GUI (engine stopped)

if Carla.isPlugin:
self.ui.act_file_new.setEnabled(False)
self.ui.act_file_open.setEnabled(False)
self.ui.act_engine_start.setEnabled(False)
self.ui.act_engine_stop.setEnabled(False)
self.ui.menu_Engine.setEnabled(False)
else:
self.ui.act_engine_start.setEnabled(True)

self.ui.act_file_save.setEnabled(False)
self.ui.act_file_save_as.setEnabled(False)
self.ui.act_engine_start.setEnabled(True)
self.ui.act_engine_stop.setEnabled(False)
self.ui.act_plugin_remove_all.setEnabled(False)
#self.ui.menu_Plugins.setEnabled(False)

self.ui.menu_PluginMacros.setEnabled(False)
self.ui.menu_Canvas.setEnabled(False)

self.setTransportMenuEnabled(False)
@@ -254,10 +263,10 @@ class HostWindow(QMainWindow):
# -------------------------------------------------------------
# Final setup

if NSM_URL:
if Carla.isPlugin:
QTimer.singleShot(0, self.slot_engineStart)
elif NSM_URL:
Carla.host.nsm_ready()
#else:
#QTimer.singleShot(0, self.slot_engineStart)

# -----------------------------------------------------------------
# Called by containers
@@ -266,116 +275,6 @@ class HostWindow(QMainWindow):
dialog = CarlaSettingsW(self, hasCanvas, hasCanvasGL)
return dialog.exec_()

def loadSettings(self, doGeometry):
settings = QSettings()

if doGeometry:
self.restoreGeometry(settings.value("Geometry", ""))

showToolbar = settings.value("ShowToolbar", True, type=bool)
self.ui.act_settings_show_toolbar.setChecked(showToolbar)
self.ui.toolBar.setVisible(showToolbar)

#if settings.contains("SplitterState"):
#self.ui.splitter.restoreState(settings.value("SplitterState", ""))
#else:
#self.ui.splitter.setSizes([99999, 210])

#diskFolders = toList(settings.value("DiskFolders", [HOME]))

#self.ui.cb_disk.setItemData(0, HOME)

#for i in range(len(diskFolders)):
#if i == 0: continue
#folder = diskFolders[i]
#self.ui.cb_disk.addItem(os.path.basename(folder), folder)

if MACOS and not settings.value("Main/UseProTheme", True, type=bool):
self.setUnifiedTitleAndToolBarOnMac(True)

useCustomMiniCanvasPaint = bool(settings.value("Main/UseProTheme", True, type=bool) and
settings.value("Main/ProThemeColor", "Black", type=str) == "Black")

# ---------------------------------------------
# engine

self.setEngineSettings(settings)

# ---------------------------------------------
# plugin checks

if settings.value("Engine/DisableChecks", False, type=bool):
os.environ["CARLA_DISCOVERY_NO_PROCESSING_CHECKS"] = "true"

elif os.getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS"):
os.environ.pop("CARLA_DISCOVERY_NO_PROCESSING_CHECKS")

# ---------------------------------------------
# plugin paths

LADSPA_PATH = toList(settings.value("Paths/LADSPA", Carla.DEFAULT_LADSPA_PATH))
DSSI_PATH = toList(settings.value("Paths/DSSI", Carla.DEFAULT_DSSI_PATH))
LV2_PATH = toList(settings.value("Paths/LV2", Carla.DEFAULT_LV2_PATH))
VST_PATH = toList(settings.value("Paths/VST", Carla.DEFAULT_VST_PATH))
AU_PATH = toList(settings.value("Paths/AU", Carla.DEFAULT_AU_PATH))
CSOUND_PATH = toList(settings.value("Paths/CSOUND", Carla.DEFAULT_CSOUND_PATH))
GIG_PATH = toList(settings.value("Paths/GIG", Carla.DEFAULT_GIG_PATH))
SF2_PATH = toList(settings.value("Paths/SF2", Carla.DEFAULT_SF2_PATH))
SFZ_PATH = toList(settings.value("Paths/SFZ", Carla.DEFAULT_SFZ_PATH))

os.environ["LADSPA_PATH"] = splitter.join(LADSPA_PATH)
os.environ["DSSI_PATH"] = splitter.join(DSSI_PATH)
os.environ["LV2_PATH"] = splitter.join(LV2_PATH)
os.environ["VST_PATH"] = splitter.join(VST_PATH)
os.environ["AU_PATH"] = splitter.join(AU_PATH)
os.environ["CSOUND_PATH"] = splitter.join(CSOUND_PATH)
os.environ["GIG_PATH"] = splitter.join(GIG_PATH)
os.environ["SF2_PATH"] = splitter.join(SF2_PATH)
os.environ["SFZ_PATH"] = splitter.join(SFZ_PATH)

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

self.fSavedSettings = {
"Main/DefaultProjectFolder": settings.value("Main/DefaultProjectFolder", HOME, type=str),
"Main/RefreshInterval": settings.value("Main/RefreshInterval", 50, type=int),
"Canvas/Theme": settings.value("Canvas/Theme", CANVAS_DEFAULT_THEME_NAME, type=str),
"Canvas/AutoHideGroups": settings.value("Canvas/AutoHideGroups", False, type=bool),
"Canvas/UseBezierLines": settings.value("Canvas/UseBezierLines", True, type=bool),
"Canvas/EyeCandy": settings.value("Canvas/EyeCandy", CANVAS_EYECANDY_SMALL, type=int),
"Canvas/UseOpenGL": settings.value("Canvas/UseOpenGL", False, type=bool),
"Canvas/Antialiasing": settings.value("Canvas/Antialiasing", CANVAS_ANTIALIASING_SMALL, type=int),
"Canvas/HighQualityAntialiasing": settings.value("Canvas/HighQualityAntialiasing", False, type=bool),
"UseCustomMiniCanvasPaint": useCustomMiniCanvasPaint
}

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

if self.fIdleTimerFast != 0:
self.killTimer(self.fIdleTimerFast)
self.fIdleTimerFast = self.startTimer(self.fSavedSettings["Main/RefreshInterval"])

if self.fIdleTimerSlow != 0:
self.killTimer(self.fIdleTimerSlow)
self.fIdleTimerSlow = self.startTimer(self.fSavedSettings["Main/RefreshInterval"]*2)

def saveSettings(self):
settings = QSettings()

settings.setValue("Geometry", self.saveGeometry())
#settings.setValue("SplitterState", self.ui.splitter.saveState())
settings.setValue("ShowToolbar", self.ui.toolBar.isVisible())
#settings.setValue("HorizontalScrollBarValue", self.ui.graphicsView.horizontalScrollBar().value())
#settings.setValue("VerticalScrollBarValue", self.ui.graphicsView.verticalScrollBar().value())

#diskFolders = []

#for i in range(self.ui.cb_disk.count()):
#diskFolders.append(self.ui.cb_disk.itemData(i))

#settings.setValue("DiskFolders", diskFolders)

self.fContainer.saveSettings(settings)

# -----------------------------------------------------------------
# Internal stuff (files)

@@ -410,6 +309,9 @@ class HostWindow(QMainWindow):
# Internal stuff (engine)

def setEngineSettings(self, settings = None):
if Carla.isPlugin:
return "Plugin"

if settings is None: settings = QSettings()

forceStereo = settings.value("Engine/ForceStereo", CARLA_DEFAULT_FORCE_STEREO, type=bool)
@@ -602,6 +504,118 @@ class HostWindow(QMainWindow):
self.ui.act_transport_forwards.setEnabled(enabled)
self.ui.menu_Transport.setEnabled(enabled)

# -----------------------------------------------------------------
# Internal stuff (settings)

def loadSettings(self, doGeometry):
settings = QSettings()

if doGeometry:
self.restoreGeometry(settings.value("Geometry", ""))

showToolbar = settings.value("ShowToolbar", True, type=bool)
self.ui.act_settings_show_toolbar.setChecked(showToolbar)
self.ui.toolBar.setVisible(showToolbar)

#if settings.contains("SplitterState"):
#self.ui.splitter.restoreState(settings.value("SplitterState", ""))
#else:
#self.ui.splitter.setSizes([99999, 210])

#diskFolders = toList(settings.value("DiskFolders", [HOME]))

#self.ui.cb_disk.setItemData(0, HOME)

#for i in range(len(diskFolders)):
#if i == 0: continue
#folder = diskFolders[i]
#self.ui.cb_disk.addItem(os.path.basename(folder), folder)

if MACOS and not settings.value("Main/UseProTheme", True, type=bool):
self.setUnifiedTitleAndToolBarOnMac(True)

# ---------------------------------------------
# plugin checks

if settings.value("Engine/DisableChecks", False, type=bool):
os.environ["CARLA_DISCOVERY_NO_PROCESSING_CHECKS"] = "true"

elif os.getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS"):
os.environ.pop("CARLA_DISCOVERY_NO_PROCESSING_CHECKS")

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

if not Carla.isPlugin:
# engine
self.setEngineSettings(settings)

# plugin paths
LADSPA_PATH = toList(settings.value("Paths/LADSPA", Carla.DEFAULT_LADSPA_PATH))
DSSI_PATH = toList(settings.value("Paths/DSSI", Carla.DEFAULT_DSSI_PATH))
LV2_PATH = toList(settings.value("Paths/LV2", Carla.DEFAULT_LV2_PATH))
VST_PATH = toList(settings.value("Paths/VST", Carla.DEFAULT_VST_PATH))
AU_PATH = toList(settings.value("Paths/AU", Carla.DEFAULT_AU_PATH))
CSOUND_PATH = toList(settings.value("Paths/CSOUND", Carla.DEFAULT_CSOUND_PATH))
GIG_PATH = toList(settings.value("Paths/GIG", Carla.DEFAULT_GIG_PATH))
SF2_PATH = toList(settings.value("Paths/SF2", Carla.DEFAULT_SF2_PATH))
SFZ_PATH = toList(settings.value("Paths/SFZ", Carla.DEFAULT_SFZ_PATH))

os.environ["LADSPA_PATH"] = splitter.join(LADSPA_PATH)
os.environ["DSSI_PATH"] = splitter.join(DSSI_PATH)
os.environ["LV2_PATH"] = splitter.join(LV2_PATH)
os.environ["VST_PATH"] = splitter.join(VST_PATH)
os.environ["AU_PATH"] = splitter.join(AU_PATH)
os.environ["CSOUND_PATH"] = splitter.join(CSOUND_PATH)
os.environ["GIG_PATH"] = splitter.join(GIG_PATH)
os.environ["SF2_PATH"] = splitter.join(SF2_PATH)
os.environ["SFZ_PATH"] = splitter.join(SFZ_PATH)

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

useCustomMiniCanvasPaint = bool(settings.value("Main/UseProTheme", True, type=bool) and
settings.value("Main/ProThemeColor", "Black", type=str) == "Black")

self.fSavedSettings = {
"Main/DefaultProjectFolder": settings.value("Main/DefaultProjectFolder", HOME, type=str),
"Main/RefreshInterval": settings.value("Main/RefreshInterval", 50, type=int),
"Canvas/Theme": settings.value("Canvas/Theme", CANVAS_DEFAULT_THEME_NAME, type=str),
"Canvas/AutoHideGroups": settings.value("Canvas/AutoHideGroups", False, type=bool),
"Canvas/UseBezierLines": settings.value("Canvas/UseBezierLines", True, type=bool),
"Canvas/EyeCandy": settings.value("Canvas/EyeCandy", CANVAS_EYECANDY_SMALL, type=int),
"Canvas/UseOpenGL": settings.value("Canvas/UseOpenGL", False, type=bool),
"Canvas/Antialiasing": settings.value("Canvas/Antialiasing", CANVAS_ANTIALIASING_SMALL, type=int),
"Canvas/HighQualityAntialiasing": settings.value("Canvas/HighQualityAntialiasing", False, type=bool),
"UseCustomMiniCanvasPaint": useCustomMiniCanvasPaint
}

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

if self.fIdleTimerFast != 0:
self.killTimer(self.fIdleTimerFast)
self.fIdleTimerFast = self.startTimer(self.fSavedSettings["Main/RefreshInterval"])

if self.fIdleTimerSlow != 0:
self.killTimer(self.fIdleTimerSlow)
self.fIdleTimerSlow = self.startTimer(self.fSavedSettings["Main/RefreshInterval"]*2)

def saveSettings(self):
settings = QSettings()

settings.setValue("Geometry", self.saveGeometry())
#settings.setValue("SplitterState", self.ui.splitter.saveState())
settings.setValue("ShowToolbar", self.ui.toolBar.isVisible())
#settings.setValue("HorizontalScrollBarValue", self.ui.graphicsView.horizontalScrollBar().value())
#settings.setValue("VerticalScrollBarValue", self.ui.graphicsView.verticalScrollBar().value())

#diskFolders = []

#for i in range(self.ui.cb_disk.count()):
#diskFolders.append(self.ui.cb_disk.itemData(i))

#settings.setValue("DiskFolders", diskFolders)

self.fContainer.saveSettings(settings)

# -----------------------------------------------------------------
# Internal stuff (gui)

@@ -680,43 +694,51 @@ class HostWindow(QMainWindow):
if doStart: self.startEngine()

check = Carla.host.is_engine_running()
self.ui.act_file_save.setEnabled(check)
self.ui.act_engine_start.setEnabled(not check)
self.ui.act_engine_stop.setEnabled(check)
self.ui.menu_PluginMacros.setEnabled(check)
self.ui.menu_Canvas.setEnabled(check)

if self.fSessionManagerName != "Non Session Manager":
self.ui.act_file_open.setEnabled(check)
self.ui.act_file_save_as.setEnabled(check)
if not Carla.isPlugin:
self.ui.act_file_save.setEnabled(check)
self.ui.act_engine_start.setEnabled(not check)
self.ui.act_engine_stop.setEnabled(check)

if self.fSessionManagerName != "Non Session Manager":
self.ui.act_file_open.setEnabled(check)
self.ui.act_file_save_as.setEnabled(check)

self.setTransportMenuEnabled(check)

if check:
#self.fInfoText = "Engine running | SampleRate: %g | BufferSize: %i" % (self.fSampleRate, self.fBufferSize)
self.refreshTransport(True)
self.fContainer.engineStarted()

self.setTransportMenuEnabled(check)
if not Carla.isPlugin:
self.refreshTransport(True)

@pyqtSlot()
def slot_engineStop(self, doStop = True):
if doStop: self.stopEngine()

check = Carla.host.is_engine_running()
self.ui.act_file_save.setEnabled(check)
self.ui.act_engine_start.setEnabled(not check)
self.ui.act_engine_stop.setEnabled(check)
self.ui.menu_PluginMacros.setEnabled(check)
self.ui.menu_Canvas.setEnabled(check)

if self.fSessionManagerName != "Non Session Manager":
self.ui.act_file_open.setEnabled(check)
self.ui.act_file_save_as.setEnabled(check)
if not Carla.isPlugin:
self.ui.act_file_save.setEnabled(check)
self.ui.act_engine_start.setEnabled(not check)
self.ui.act_engine_stop.setEnabled(check)

if self.fSessionManagerName != "Non Session Manager":
self.ui.act_file_open.setEnabled(check)
self.ui.act_file_save_as.setEnabled(check)

self.setTransportMenuEnabled(check)

if not check:
self.fContainer.engineStopped()
#self.fInfoText = ""
#self.fInfoLabel.setText("Engine stopped")

self.setTransportMenuEnabled(check)

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

@pyqtSlot()
@@ -884,9 +906,11 @@ class HostWindow(QMainWindow):

def timerEvent(self, event):
if event.timerId() == self.fIdleTimerFast:
Carla.host.engine_idle()
if not Carla.isPlugin:
Carla.host.engine_idle()
self.refreshTransport()

self.fContainer.idleFast()
self.refreshTransport()

elif event.timerId() == self.fIdleTimerSlow:
self.fContainer.idleSlow()


+ 25
- 25
source/carla_patchbay.py View File

@@ -38,10 +38,10 @@ from carla_widgets import *
# Try Import OpenGL

try:
#try:
from PyQt5.QtOpenGL import QGLWidget
#except:
#from PyQt4.QtOpenGL import QGLWidget
try:
from PyQt5.QtOpenGL import QGLWidget
except:
from PyQt4.QtOpenGL import QGLWidget
hasGL = True
except:
hasGL = False
@@ -65,17 +65,17 @@ class CarlaPatchbayW(QGraphicsView):

self.scene = patchcanvas.PatchScene(self, self) # FIXME?
self.setScene(self.scene)
#self.setRenderHint(QPainter.Antialiasing, bool(self.fSavedSettings["Canvas/Antialiasing"] == patchcanvas.ANTIALIASING_FULL))
#if self.fSavedSettings["Canvas/UseOpenGL"] and hasGL:
#self.setViewport(QGLWidget(self))
#self.setRenderHint(QPainter.HighQualityAntialiasing, self.fSavedSettings["Canvas/HighQualityAntialiasing"])
#pOptions = patchcanvas.options_t()
#pOptions.theme_name = self.fSavedSettings["Canvas/Theme"]
#pOptions.auto_hide_groups = self.fSavedSettings["Canvas/AutoHideGroups"]
#pOptions.use_bezier_lines = self.fSavedSettings["Canvas/UseBezierLines"]
#pOptions.antialiasing = self.fSavedSettings["Canvas/Antialiasing"]
#pOptions.eyecandy = self.fSavedSettings["Canvas/EyeCandy"]
self.setRenderHint(QPainter.Antialiasing, bool(parent.fSavedSettings["Canvas/Antialiasing"] == patchcanvas.ANTIALIASING_FULL))
if parent.fSavedSettings["Canvas/UseOpenGL"] and hasGL:
self.setViewport(QGLWidget(self))
self.setRenderHint(QPainter.HighQualityAntialiasing, parent.fSavedSettings["Canvas/HighQualityAntialiasing"])
pOptions = patchcanvas.options_t()
pOptions.theme_name = parent.fSavedSettings["Canvas/Theme"]
pOptions.auto_hide_groups = parent.fSavedSettings["Canvas/AutoHideGroups"]
pOptions.use_bezier_lines = parent.fSavedSettings["Canvas/UseBezierLines"]
pOptions.antialiasing = parent.fSavedSettings["Canvas/Antialiasing"]
pOptions.eyecandy = parent.fSavedSettings["Canvas/EyeCandy"]

pFeatures = patchcanvas.features_t()
pFeatures.group_info = False
@@ -84,7 +84,7 @@ class CarlaPatchbayW(QGraphicsView):
pFeatures.port_rename = False
pFeatures.handle_group_pos = True

#patchcanvas.setOptions(pOptions)
patchcanvas.setOptions(pOptions)
patchcanvas.setFeatures(pFeatures)
patchcanvas.init("Carla", self.scene, CanvasCallback, True)

@@ -334,18 +334,18 @@ class CarlaPatchbayW(QGraphicsView):

@pyqtSlot()
def slot_configureCarla(self):
if self.fParent is None or not self.fParent.openSettings(False, False):
if self.fParent is None or not self.fParent.openSettingsWindow(False, False):
return

#self.loadSettings(False)
self.fParent.loadSettings(False)
patchcanvas.clear()

#pOptions = patchcanvas.options_t()
#pOptions.theme_name = self.fSavedSettings["Canvas/Theme"]
#pOptions.auto_hide_groups = self.fSavedSettings["Canvas/AutoHideGroups"]
#pOptions.use_bezier_lines = self.fSavedSettings["Canvas/UseBezierLines"]
#pOptions.antialiasing = self.fSavedSettings["Canvas/Antialiasing"]
#pOptions.eyecandy = self.fSavedSettings["Canvas/EyeCandy"]
pOptions = patchcanvas.options_t()
pOptions.theme_name = self.fParent.fSavedSettings["Canvas/Theme"]
pOptions.auto_hide_groups = self.fParent.fSavedSettings["Canvas/AutoHideGroups"]
pOptions.use_bezier_lines = self.fParent.fSavedSettings["Canvas/UseBezierLines"]
pOptions.antialiasing = self.fParent.fSavedSettings["Canvas/Antialiasing"]
pOptions.eyecandy = self.fParent.fSavedSettings["Canvas/EyeCandy"]

pFeatures = patchcanvas.features_t()
pFeatures.group_info = False
@@ -354,7 +354,7 @@ class CarlaPatchbayW(QGraphicsView):
pFeatures.port_rename = False
pFeatures.handle_group_pos = True

#patchcanvas.setOptions(pOptions)
patchcanvas.setOptions(pOptions)
patchcanvas.setFeatures(pFeatures)
patchcanvas.init("Carla", self.scene, CanvasCallback, False)



+ 2
- 2
source/carla_rack.py View File

@@ -329,10 +329,10 @@ class CarlaRackW(QListWidget):

@pyqtSlot()
def slot_configureCarla(self):
if self.fParent is None or not self.fParent.openSettings(False, False):
if self.fParent is None or not self.fParent.openSettingsWindow(False, False):
return

#self.loadSettings(False)
self.loadSettings(False)

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



+ 8
- 0
source/carla_settings.py View File

@@ -216,6 +216,14 @@ class CarlaSettingsW(QDialog):
self.ui.group_theme.setEnabled(False)
self.ui.ch_theme_pro.setChecked(False)

if Carla.isPlugin:
self.ui.lw_page.hideRow(self.TAB_INDEX_CARLA_ENGINE)
self.ui.lw_page.hideRow(self.TAB_INDEX_CARLA_PATHS)

#from PyQt4.QtGui import QTableWidget
#x = QTableWidget(self)
#x.()

# -------------------------------------------------------------
# Set-up connections



+ 4
- 1
source/carla_shared.py View File

@@ -311,8 +311,10 @@ class CarlaObject(object):
'gui',
# bool, is controller
'isControl',
# bool, is controller local
# bool, is running local
'isLocal',
# bool, is plugin
'isPlugin',
# current process mode
'processMode',
# current max parameters
@@ -340,6 +342,7 @@ Carla.host = None
Carla.gui = None
Carla.isControl = False
Carla.isLocal = True
Carla.isPlugin = False
Carla.processMode = PROCESS_MODE_MULTIPLE_CLIENTS if LINUX else PROCESS_MODE_CONTINUOUS_RACK
Carla.maxParameters = MAX_DEFAULT_PARAMETERS



+ 3
- 1
source/carla_widgets.py View File

@@ -102,6 +102,8 @@ class CarlaAboutW(QDialog):

if Carla.isControl:
extraInfo = " - <b>%s</b>" % self.tr("OSC Bridge Version")
elif Carla.isPlugin:
extraInfo = " - <b>%s</b>" % self.tr("Plugin Version")
else:
extraInfo = ""

@@ -111,7 +113,7 @@ class CarlaAboutW(QDialog):
"<br>Copyright (C) 2011-2013 falkTX<br>"
"" % (VERSION, extraInfo)))

if Carla.host is None:
if Carla.isControl or Carla.isPlugin or Carla.host is None:
self.ui.l_extended.hide()
self.ui.tabWidget.removeTab(1)
self.ui.tabWidget.removeTab(1)


source/modules/carla_native/resources/externalui.py → source/externalui.py View File


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

@@ -337,6 +337,10 @@ const char* CallbackType2Str(const CallbackType type)
return "CALLBACK_SAMPLE_RATE_CHANGED";
case CALLBACK_PROCESS_MODE_CHANGED:
return "CALLBACK_PROCESS_MODE_CHANGED";
case CALLBACK_ENGINE_STARTED:
return "CALLBACK_ENGINE_STARTED";
case CALLBACK_ENGINE_STOPPED:
return "CALLBACK_ENGINE_STOPPED";
case CALLBACK_NSM_ANNOUNCE:
return "CALLBACK_NSM_ANNOUNCE";
case CALLBACK_NSM_OPEN:


Loading…
Cancel
Save