Browse Source

More cleanup & fixing, implement plugin rename when possible

tags/1.9.4
falkTX 12 years ago
parent
commit
ad83895d40
18 changed files with 268 additions and 65 deletions
  1. +2
    -2
      source/backend/CarlaEngine.hpp
  2. +9
    -2
      source/backend/CarlaPlugin.hpp
  3. +112
    -29
      source/backend/engine/CarlaEngine.cpp
  4. +10
    -2
      source/backend/engine/CarlaEngineInternal.hpp
  5. +60
    -0
      source/backend/engine/CarlaEngineJack.cpp
  6. +2
    -2
      source/backend/plugin/BridgePlugin.cpp
  7. +12
    -2
      source/backend/plugin/CarlaPlugin.cpp
  8. +5
    -0
      source/backend/plugin/CarlaPluginInternal.hpp
  9. +3
    -3
      source/backend/plugin/DssiPlugin.cpp
  10. +2
    -2
      source/backend/plugin/FluidSynthPlugin.cpp
  11. +4
    -4
      source/backend/plugin/LadspaPlugin.cpp
  12. +2
    -2
      source/backend/plugin/LinuxSamplerPlugin.cpp
  13. +3
    -3
      source/backend/plugin/NativePlugin.cpp
  14. +3
    -3
      source/backend/plugin/VstPlugin.cpp
  15. +1
    -1
      source/carla_backend.py
  16. +20
    -1
      source/carla_shared.py
  17. +17
    -7
      source/libs/jackbridge/JackBridge.cpp
  18. +1
    -0
      source/libs/jackbridge/JackBridge.hpp

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

@@ -730,7 +730,7 @@ public:
* Rename plugin with id \a id to \a newName.\n
* Returns the new name, or nullptr if the operation failed.
*/
const char* renamePlugin(const unsigned int id, const char* const newName);
virtual const char* renamePlugin(const unsigned int id, const char* const newName);

/*!
* Clone plugin with id \a id.
@@ -764,7 +764,7 @@ public:
* Get a unique plugin name within the engine.\n
* Returned variable must NOT be free'd.
*/
const char* getNewUniquePluginName(const char* const name);
const char* getUniquePluginName(const char* const name);

// -------------------------------------------------------------------
// Project management


+ 9
- 2
source/backend/CarlaPlugin.hpp View File

@@ -422,11 +422,18 @@ public:
// Set data (internal stuff)

/*!
* Set the plugin's id to \a id.
* Set the plugin's id to \a newId.
*
* \see id()
*/
void setId(const unsigned int id);
void setId(const unsigned int newId);

/*!
* Set the plugin's name to \a newName.
*
* \see name()
*/
void setName(const char* const newName);

/*!
* Set a plugin's option.


+ 112
- 29
source/backend/engine/CarlaEngine.cpp View File

@@ -403,6 +403,23 @@ void doPluginRemove(CarlaEngineProtectedData* const kData, const bool unlock)
kData->nextAction.mutex.unlock();
}

void doPluginsSwitch(CarlaEngineProtectedData* const kData, const bool unlock)
{
CARLA_ASSERT(kData->curPluginCount >= 2);

const unsigned int idA = kData->nextAction.pluginId;
const unsigned int idB = kData->nextAction.value;

CarlaPlugin* const tmp = kData->plugins[idA].plugin;
kData->plugins[idA].plugin = kData->plugins[idB].plugin;
kData->plugins[idB].plugin = tmp;

kData->nextAction.opcode = EnginePostActionNull;

if (unlock)
kData->nextAction.mutex.unlock();
}

const char* findDSSIGUI(const char* const filename, const char* const label)
{
QString guiFilename;
@@ -796,7 +813,6 @@ bool CarlaEngine::removePlugin(const unsigned int id)

if (plugin == nullptr)
{
carla_stderr("CarlaEngine::removePlugin(%i) - could not find plugin", id);
setLastError("Could not find plugin to remove");
return false;
}
@@ -877,7 +893,34 @@ void CarlaEngine::removeAllPlugins()

const char* CarlaEngine::renamePlugin(const unsigned int id, const char* const newName)
{
setLastError("Not implemented yet");
CARLA_ASSERT(kData->curPluginCount > 0);
CARLA_ASSERT(id < kData->curPluginCount);
CARLA_ASSERT(kData->plugins != nullptr);
CARLA_ASSERT(newName != nullptr);

if (kData->plugins == nullptr)
{
setLastError("Critical error: no plugins are currently loaded!");
return nullptr;
}

CarlaPlugin* const plugin = kData->plugins[id].plugin;

if (plugin == nullptr)
{
carla_stderr("CarlaEngine::clonePlugin(%i) - could not find plugin", id);
return nullptr;
}

CARLA_ASSERT(plugin->id() == id);

if (const char* const name = getUniquePluginName(newName))
{
plugin->setName(name);

return name;
}

return nullptr;
}

@@ -896,43 +939,40 @@ bool CarlaEngine::clonePlugin(const unsigned int id)

CarlaPlugin* const plugin = kData->plugins[id].plugin;

CARLA_ASSERT(plugin != nullptr);

if (plugin != nullptr)
if (plugin == nullptr)
{
CARLA_ASSERT(plugin->id() == id);
carla_stderr("CarlaEngine::clonePlugin(%i) - could not find plugin", id);
return false;
}

CARLA_ASSERT(plugin->id() == id);

const SaveState& saveState(plugin->getSaveState());
const SaveState& saveState(plugin->getSaveState());

char label[STR_MAX+1] = { '\0' };
plugin->getLabel(label);
char label[STR_MAX+1] = { '\0' };
plugin->getLabel(label);

BinaryType binaryType = BINARY_NATIVE;
BinaryType binaryType = BINARY_NATIVE;

#ifndef BUILD_BRIDGE
if (plugin->hints() & PLUGIN_IS_BRIDGE)
binaryType = CarlaPluginGetBridgeBinaryType(plugin);
if (plugin->hints() & PLUGIN_IS_BRIDGE)
binaryType = CarlaPluginGetBridgeBinaryType(plugin);
#endif

const unsigned int pluginsBefore(kData->curPluginCount);
const unsigned int pluginsBefore(kData->curPluginCount);

if (! addPlugin(binaryType, plugin->type(), plugin->filename(), plugin->name(), label, plugin->getExtraStuff()))
return false;

CARLA_ASSERT(pluginsBefore+1 == kData->curPluginCount);
if (! addPlugin(binaryType, plugin->type(), plugin->filename(), plugin->name(), label, plugin->getExtraStuff()))
return false;

CarlaPlugin* const newPlugin = kData->plugins[kData->curPluginCount-1].plugin;
CARLA_ASSERT(pluginsBefore+1 == kData->curPluginCount);

CARLA_ASSERT(newPlugin != nullptr);
CarlaPlugin* const newPlugin = kData->plugins[kData->curPluginCount-1].plugin;

newPlugin->loadSaveState(saveState);
CARLA_ASSERT(newPlugin != nullptr);

return true;
}
newPlugin->loadSaveState(saveState);

carla_stderr("CarlaEngine::clonePlugin(%i) - could not find plugin", id);
setLastError("Could not find plugin to clone");
return false;
return true;
}

bool CarlaEngine::replacePlugin(const unsigned int id)
@@ -943,8 +983,48 @@ bool CarlaEngine::replacePlugin(const unsigned int id)

bool CarlaEngine::switchPlugins(const unsigned int idA, const unsigned int idB)
{
setLastError("Not implemented yet");
return false;
CARLA_ASSERT(kData->curPluginCount > 0);
CARLA_ASSERT(idA < kData->curPluginCount);
CARLA_ASSERT(idB < kData->curPluginCount);
CARLA_ASSERT(kData->plugins != nullptr);

if (kData->plugins == nullptr)
{
setLastError("Critical error: no plugins are currently loaded!");
return false;
}

kData->thread.stopNow();

kData->nextAction.pluginId = idA;
kData->nextAction.value = idB;
kData->nextAction.opcode = EnginePostActionSwitchPlugins;

kData->nextAction.mutex.lock();

if (isRunning())
{
carla_stderr("CarlaEngine::switchPlugins(%i, %i) - switch blocking START", idA, idB);
// block wait for unlock on proccessing side
kData->nextAction.mutex.lock();
carla_stderr("CarlaEngine::switchPlugins(%i, %i) - switch blocking DONE", idA, idB);
}
else
{
doPluginsSwitch(kData, false);
}

#ifndef BUILD_BRIDGE // TODO
//if (isOscControlRegistered())
// osc_send_control_remove_plugin(id);
#endif

kData->nextAction.mutex.unlock();

if (isRunning() && ! kData->aboutToClose)
kData->thread.startNow();

return true;
}

CarlaPlugin* CarlaEngine::getPlugin(const unsigned int id) const
@@ -965,9 +1045,9 @@ CarlaPlugin* CarlaEngine::getPluginUnchecked(const unsigned int id) const
return kData->plugins[id].plugin;
}

const char* CarlaEngine::getNewUniquePluginName(const char* const name)
const char* CarlaEngine::getUniquePluginName(const char* const name)
{
carla_debug("CarlaEngine::getNewUniquePluginName(\"%s\")", name);
carla_debug("CarlaEngine::getUniquePluginName(\"%s\")", name);
CARLA_ASSERT(kData->maxPluginNumber > 0);
CARLA_ASSERT(kData->plugins != nullptr);
CARLA_ASSERT(name != nullptr);
@@ -1486,6 +1566,9 @@ void CarlaEngine::proccessPendingEvents()
case EnginePostActionRemovePlugin:
doPluginRemove(kData, true);
break;
case EnginePostActionSwitchPlugins:
doPluginsSwitch(kData, true);
break;
}

if (kData->time.playing)


+ 10
- 2
source/backend/engine/CarlaEngineInternal.hpp View File

@@ -116,7 +116,8 @@ const unsigned short RACK_EVENT_COUNT = 512;

enum EnginePostAction {
EnginePostActionNull,
EnginePostActionRemovePlugin
EnginePostActionRemovePlugin,
EnginePostActionSwitchPlugins
};

struct EnginePluginData {
@@ -151,11 +152,18 @@ struct CarlaEngineProtectedData {
struct NextAction {
EnginePostAction opcode;
unsigned int pluginId;
unsigned int value;
CarlaMutex mutex;

NextAction()
: opcode(EnginePostActionNull),
pluginId(0) {}
pluginId(0),
value(0) {}

~NextAction()
{
CARLA_ASSERT(opcode == EnginePostActionNull);
}

void ready()
{


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

@@ -38,6 +38,7 @@ CARLA_BACKEND_START_NAMESPACE
// Plugin Helpers, defined in CarlaPlugin.cpp

extern CarlaEngine* CarlaPluginGetEngine(CarlaPlugin* const plugin);
extern CarlaEngineClient* CarlaPluginGetEngineClient(CarlaPlugin* const plugin);
extern CarlaEngineAudioPort* CarlaPluginGetAudioInPort(CarlaPlugin* const plugin, uint32_t index);
extern CarlaEngineAudioPort* CarlaPluginGetAudioOutPort(CarlaPlugin* const plugin, uint32_t index);

@@ -485,6 +486,7 @@ private:
jack_client_t* const kClient;
const bool kUseClient;

friend class CarlaEngineJack;
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackClient)
};

@@ -737,6 +739,64 @@ public:
return new CarlaEngineJackClient(kEngineTypeJack, fOptions.processMode, client);
}

const char* renamePlugin(const unsigned int id, const char* const newName) override
{
CARLA_ASSERT(kData->curPluginCount > 0);
CARLA_ASSERT(id < kData->curPluginCount);
CARLA_ASSERT(kData->plugins != nullptr);
CARLA_ASSERT(newName != nullptr);

if (kData->plugins == nullptr)
{
setLastError("Critical error: no plugins are currently loaded!");
return nullptr;
}

CarlaPlugin* const plugin = kData->plugins[id].plugin;

if (plugin == nullptr)
{
carla_stderr("CarlaEngine::clonePlugin(%i) - could not find plugin", id);
return nullptr;
}

CARLA_ASSERT(plugin->id() == id);

const char* name = getUniquePluginName(newName);

// JACK client rename
if (fOptions.processMode == PROCESS_MODE_MULTIPLE_CLIENTS)
{
// not supported yet in the JACK API
if (bridge.client_rename_ptr != nullptr)
{
jack_client_t* const client = ((CarlaEngineJackClient*)CarlaPluginGetEngineClient(plugin))->kClient;
name = bridge.client_rename_ptr(client, name);
}
else
{
setLastError("Your current JACK version does not allow renaming of clients");
return nullptr;
}
}

if (name == nullptr)
return nullptr;

// Rename
plugin->setName(name);

if (fOptions.processMode == PROCESS_MODE_SINGLE_CLIENT)
{
// reload plugin to recreate its ports
const SaveState& saveState(plugin->getSaveState());
plugin->reload();
plugin->loadSaveState(saveState);
}

return name;
}

#ifndef BUILD_BRIDGE
// -------------------------------------------------------------------
// Patchbay


+ 2
- 2
source/backend/plugin/BridgePlugin.cpp View File

@@ -449,7 +449,7 @@ public:
fInfo.copyright = copyright;

if (fName.isEmpty())
fName = kData->engine->getNewUniquePluginName(name);
fName = kData->engine->getUniquePluginName(name);

break;
}
@@ -1140,7 +1140,7 @@ public:
// set info

if (name != nullptr)
fName = kData->engine->getNewUniquePluginName(name);
fName = kData->engine->getUniquePluginName(name);

fFilename = filename;



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

@@ -235,6 +235,11 @@ CarlaEngine* CarlaPluginGetEngine(CarlaPlugin* const plugin)
return CarlaPluginProtectedData::getEngine(plugin);
}

CarlaEngineClient* CarlaPluginGetEngineClient(CarlaPlugin* const plugin)
{
return CarlaPluginProtectedData::getEngineClient(plugin);
}

CarlaEngineAudioPort* CarlaPluginGetAudioInPort(CarlaPlugin* const plugin, const uint32_t index)
{
return CarlaPluginProtectedData::getAudioInPort(plugin, index);
@@ -977,9 +982,14 @@ bool CarlaPlugin::loadStateFromFile(const char* const filename)
// -------------------------------------------------------------------
// Set data (internal stuff)

void CarlaPlugin::setId(const unsigned int id)
void CarlaPlugin::setId(const unsigned int newId)
{
fId = newId;
}

void CarlaPlugin::setName(const char* const newName)
{
fId = id;
fName = newName;
}

void CarlaPlugin::setOption(const unsigned int option, const bool yesNo)


+ 5
- 0
source/backend/plugin/CarlaPluginInternal.hpp View File

@@ -670,6 +670,11 @@ struct CarlaPluginProtectedData {
return plugin->kData->engine;
}

static CarlaEngineClient* getEngineClient(CarlaPlugin* const plugin)
{
return plugin->kData->client;
}

static CarlaEngineAudioPort* getAudioInPort(CarlaPlugin* const plugin, const uint32_t index)
{
return plugin->kData->audioIn.ports[index].port;


+ 3
- 3
source/backend/plugin/DssiPlugin.cpp View File

@@ -1812,11 +1812,11 @@ public:
// get info

if (name != nullptr)
fName = kData->engine->getNewUniquePluginName(name);
fName = kData->engine->getUniquePluginName(name);
else if (fDescriptor->Name != nullptr)
fName = kData->engine->getNewUniquePluginName(fDescriptor->Name);
fName = kData->engine->getUniquePluginName(fDescriptor->Name);
else
fName = kData->engine->getNewUniquePluginName(fDescriptor->Label);
fName = kData->engine->getUniquePluginName(fDescriptor->Label);

fFilename = filename;



+ 2
- 2
source/backend/plugin/FluidSynthPlugin.cpp View File

@@ -1447,9 +1447,9 @@ public:
fLabel = label;

if (name != nullptr)
fName = kData->engine->getNewUniquePluginName(name);
fName = kData->engine->getUniquePluginName(name);
else
fName = kData->engine->getNewUniquePluginName(label);
fName = kData->engine->getUniquePluginName(label);

// ---------------------------------------------------------------
// register client


+ 4
- 4
source/backend/plugin/LadspaPlugin.cpp View File

@@ -1392,13 +1392,13 @@ public:
fRdfDescriptor = ladspa_rdf_dup(rdfDescriptor);

if (name != nullptr)
fName = kData->engine->getNewUniquePluginName(name);
fName = kData->engine->getUniquePluginName(name);
else if (fRdfDescriptor != nullptr && fRdfDescriptor->Title != nullptr)
fName = kData->engine->getNewUniquePluginName(fRdfDescriptor->Title);
fName = kData->engine->getUniquePluginName(fRdfDescriptor->Title);
else if (fDescriptor->Name != nullptr)
fName = kData->engine->getNewUniquePluginName(fDescriptor->Name);
fName = kData->engine->getUniquePluginName(fDescriptor->Name);
else
fName = kData->engine->getNewUniquePluginName(fDescriptor->Label);
fName = kData->engine->getUniquePluginName(fDescriptor->Label);

fFilename = filename;



+ 2
- 2
source/backend/plugin/LinuxSamplerPlugin.cpp View File

@@ -1011,9 +1011,9 @@ public:
fFilename = filename;

if (name != nullptr)
fName = kData->engine->getNewUniquePluginName(name);
fName = kData->engine->getUniquePluginName(name);
else
fName = kData->engine->getNewUniquePluginName((const char*)fRealName);
fName = kData->engine->getUniquePluginName((const char*)fRealName);

// ---------------------------------------------------------------
// Register client


+ 3
- 3
source/backend/plugin/NativePlugin.cpp View File

@@ -2049,11 +2049,11 @@ public:
// get info

if (name != nullptr)
fName = kData->engine->getNewUniquePluginName(name);
fName = kData->engine->getUniquePluginName(name);
else if (fDescriptor->name != nullptr)
fName = kData->engine->getNewUniquePluginName(fDescriptor->name);
fName = kData->engine->getUniquePluginName(fDescriptor->name);
else
fName = kData->engine->getNewUniquePluginName(label);
fName = kData->engine->getUniquePluginName(label);

// ---------------------------------------------------------------
// register client


+ 3
- 3
source/backend/plugin/VstPlugin.cpp View File

@@ -2158,7 +2158,7 @@ public:

if (name != nullptr)
{
fName = kData->engine->getNewUniquePluginName(name);
fName = kData->engine->getUniquePluginName(name);
}
else
{
@@ -2167,12 +2167,12 @@ public:

if (strBuf[0] != '\0')
{
fName = kData->engine->getNewUniquePluginName(strBuf);
fName = kData->engine->getUniquePluginName(strBuf);
}
else
{
const char* const label = std::strrchr(filename, OS_SEP)+1;
fName = kData->engine->getNewUniquePluginName(label);
fName = kData->engine->getUniquePluginName(label);
}
}



+ 1
- 1
source/carla_backend.py View File

@@ -708,7 +708,7 @@ class Host(object):
self.lib.carla_remove_all_plugins()

def rename_plugin(self, pluginId, newName):
return self.lib.carla_rename_plugin(pluginId, newName)
return self.lib.carla_rename_plugin(pluginId, newName.encode("utf-8"))

def clone_plugin(self, pluginId):
return self.lib.carla_clone_plugin(pluginId)


+ 20
- 1
source/carla_shared.py View File

@@ -26,7 +26,7 @@ from copy import deepcopy
from subprocess import Popen, PIPE
from PyQt4.QtCore import pyqtSlot, qWarning, Qt, QByteArray, QSettings, QThread, QTimer, SIGNAL, SLOT
from PyQt4.QtGui import QColor, QCursor, QDialog, QIcon, QInputDialog, QFileDialog, QFontMetrics, QFrame, QMenu
from PyQt4.QtGui import QMessageBox, QPainter, QPainterPath, QTableWidgetItem, QVBoxLayout, QWidget
from PyQt4.QtGui import QLineEdit, QMessageBox, QPainter, QPainterPath, QTableWidgetItem, QVBoxLayout, QWidget

# ------------------------------------------------------------------------------------------------------------
# Imports (Custom)
@@ -2161,6 +2161,7 @@ class PluginWidget(QFrame):

menu.addSeparator()
actClone = menu.addAction(self.tr("Clone"))
actRename = menu.addAction(self.tr("Rename..."))
actRemove = menu.addAction(self.tr("Remove"))

actSel = menu.exec_(QCursor.pos())
@@ -2179,6 +2180,24 @@ class PluginWidget(QFrame):
CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"),
cString(Carla.host.get_last_error()), QMessageBox.Ok, QMessageBox.Ok)

elif actSel == actRename:
oldName = self.fPluginInfo['name']
newNameTry = QInputDialog.getText(self, self.tr("Rename Plugin"), self.tr("New plugin name:"), QLineEdit.Normal, oldName)

if not (newNameTry[1] and newNameTry[0] and oldName != newNameTry[0]):
return

newName = newNameTry[0]

if Carla.host.rename_plugin(self.fPluginId, newName):
self.fPluginInfo['name'] = newName
self.ui.edit_dialog.fPluginInfo["name"] = newName
self.ui.edit_dialog.reloadInfo()
self.ui.label_name.setText(newName)
else:
CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"),
cString(Carla.host.get_last_error()), QMessageBox.Ok, QMessageBox.Ok)

elif actSel == actRemove:
if not Carla.host.remove_plugin(self.fPluginId):
CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"),


+ 17
- 7
source/libs/jackbridge/JackBridge.cpp View File

@@ -35,6 +35,7 @@

typedef const char* (*jacksym_get_version_string)();
typedef jack_client_t* (*jacksym_client_open)(const char*, jack_options_t, jack_status_t*, ...);
typedef const char* (*jacksym_client_rename)(jack_client_t* client, const char* new_name);

typedef int (*jacksym_client_close)(jack_client_t*);
typedef int (*jacksym_client_name_size)();
@@ -98,6 +99,7 @@ struct JackBridge {

jacksym_get_version_string get_version_string_ptr;
jacksym_client_open client_open_ptr;
jacksym_client_rename client_rename_ptr;
jacksym_client_close client_close_ptr;
jacksym_client_name_size client_name_size_ptr;
jacksym_get_client_name get_client_name_ptr;
@@ -150,6 +152,7 @@ struct JackBridge {
: lib(nullptr),
get_version_string_ptr(nullptr),
client_open_ptr(nullptr),
client_rename_ptr(nullptr),
client_close_ptr(nullptr),
client_name_size_ptr(nullptr),
get_client_name_ptr(nullptr),
@@ -197,19 +200,18 @@ struct JackBridge {
transport_query_ptr(nullptr)
{
#if defined(CARLA_OS_MAC)
lib = lib_open("libjack.dylib");
fprintf(stderr, "load JACK DLL FOR MAC\n");
const char* const filename = "libjack.dylib";
#elif defined(CARLA_OS_WIN) && ! defined(__WINE__)
lib = lib_open("libjack.dll");
fprintf(stderr, "load JACK DLL FOR WINDOWS\n");
const char* const filename = "libjack.dll";
#else
lib = lib_open("libjack.so");
fprintf(stderr, "load JACK DLL FOR LINUX\n");
const char* const filename = "libjack.so.0";
#endif

lib = lib_open(filename);

if (lib == nullptr)
{
fprintf(stderr, "Failed to load JACK DLL\n");
fprintf(stderr, "Failed to load JACK DLL, reason:\n%s\n", lib_error(filename));
return;
}

@@ -218,6 +220,7 @@ struct JackBridge {

LIB_SYMBOL(get_version_string)
LIB_SYMBOL(client_open)
LIB_SYMBOL(client_rename)
LIB_SYMBOL(client_close)
LIB_SYMBOL(client_name_size)
LIB_SYMBOL(get_client_name)
@@ -295,6 +298,13 @@ jack_client_t* jackbridge_client_open(const char* client_name, jack_options_t op
return nullptr;
}

const char* jackbridge_client_rename(jack_client_t* client, const char* new_name)
{
if (bridge.client_rename_ptr != nullptr)
return bridge.client_rename_ptr(client, new_name);
return nullptr;
}

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

bool jackbridge_client_close(jack_client_t* client)


+ 1
- 0
source/libs/jackbridge/JackBridge.hpp View File

@@ -164,6 +164,7 @@ typedef void (*JackShutdownCallback)(void *arg);

CARLA_EXPORT const char* jackbridge_get_version_string();
CARLA_EXPORT jack_client_t* jackbridge_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...);
CARLA_EXPORT const char* jackbridge_client_rename(jack_client_t* client, const char* new_name);

CARLA_EXPORT bool jackbridge_client_close(jack_client_t* client);
CARLA_EXPORT int jackbridge_client_name_size();


Loading…
Cancel
Save