Browse Source

Start options for jack-app dialog

tags/1.9.8
falkTX 8 years ago
parent
commit
27ce7fc2e1
6 changed files with 410 additions and 471 deletions
  1. +243
    -44
      resources/ui/carla_add_jack.ui
  2. +90
    -262
      source/backend/plugin/CarlaPluginJack.cpp
  3. +12
    -1
      source/carla_database.py
  4. +7
    -2
      source/carla_host.py
  5. +56
    -161
      source/libjack/libjack.cpp
  6. +2
    -1
      source/utils/CarlaStateUtils.cpp

+ 243
- 44
resources/ui/carla_add_jack.ui View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>653</width>
<height>125</height>
<width>626</width>
<height>274</height>
</rect>
</property>
<property name="windowTitle">
@@ -90,50 +90,249 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Command:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="le_command"/>
</item>
</layout>
<widget class="QGroupBox" name="group_command">
<property name="title">
<string>Command</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Command:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QLineEdit" name="le_command"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Save trigger:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="cb_save_trigger">
<property name="enabled">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>None / Manual</string>
</property>
</item>
<item>
<property name="text">
<string>SIGUSR1</string>
</property>
</item>
<item>
<property name="text">
<string>NSM</string>
</property>
</item>
</widget>
</item>
<item row="2" column="3">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>274</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_9">
<property name="text">
<string>(Not Implemented Yet)</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Name:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QLineEdit" name="le_name"/>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Flags:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="le_flags"/>
</item>
</layout>
<widget class="QGroupBox" name="group_setup">
<property name="title">
<string>Setup</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Audio inputs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="sb_audio_ins">
<property name="maximum">
<number>64</number>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
</item>
<item row="0" column="2" rowspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_5">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>CV inputs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QSpinBox" name="sb_cv_ins">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>64</number>
</property>
</widget>
</item>
<item row="0" column="5" rowspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QLabel" name="label_7">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>MIDI inputs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QSpinBox" name="sb_midi_ins">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Audio outputs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="sb_audio_outs">
<property name="maximum">
<number>64</number>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="label_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>CV outputs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QSpinBox" name="sb_cv_outs">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>64</number>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QLabel" name="label_8">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>MIDI outputs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="QSpinBox" name="sb_midi_outs">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">


+ 90
- 262
source/backend/plugin/CarlaPluginJack.cpp View File

@@ -62,14 +62,17 @@ public:
kEngine(engine),
kPlugin(plugin),
fShmIds(),
fNumPorts(),
fProcess() {}

void setData(const char* const shmIds) noexcept
void setData(const char* const shmIds, const char* const numPorts) noexcept
{
CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && shmIds[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(numPorts != nullptr && numPorts[0] != '\0',);
CARLA_SAFE_ASSERT(! isThreadRunning());

fShmIds = shmIds;
fShmIds = shmIds;
fNumPorts = numPorts;
}

uintptr_t getProcessID() const noexcept
@@ -122,7 +125,8 @@ protected:
const ScopedEnvVar sev2("LD_LIBRARY_PATH", libjackdir.buffer());

carla_setenv("CARLA_FRONTEND_WIN_ID", strBuf);
carla_setenv("CARLA_SHM_IDS", fShmIds.toRawUTF8());
carla_setenv("CARLA_SHM_IDS", fShmIds.buffer());
carla_setenv("CARLA_NUM_PORTS", fNumPorts.buffer());

started = fProcess->start(arguments);
}
@@ -177,7 +181,8 @@ private:
CarlaEngine* const kEngine;
CarlaPlugin* const kPlugin;

String fShmIds;
CarlaString fShmIds;
CarlaString fNumPorts;

ScopedPointer<ChildProcess> fProcess;

@@ -197,7 +202,7 @@ public:
fTimedError(false),
fProcCanceled(false),
fProcWaitTime(0),
fLastPongTime(-1),
fLastPingTime(-1),
fBridgeThread(engine, this),
fShmAudioPool(),
fShmRtClientControl(),
@@ -293,7 +298,7 @@ public:

void getLabel(char* const strBuf) const noexcept override
{
std::strncpy(strBuf, fInfo.label, STR_MAX);
std::strncpy(strBuf, fInfo.setupLabel, STR_MAX);
}

void getMaker(char* const strBuf) const noexcept override
@@ -308,7 +313,8 @@ public:

void getRealName(char* const strBuf) const noexcept override
{
std::strncpy(strBuf, fInfo.name, STR_MAX);
// FIXME
std::strncpy(strBuf, "Carla's libjack", STR_MAX);
}

// -------------------------------------------------------------------
@@ -369,6 +375,14 @@ public:
try {
handleNonRtData();
} CARLA_SAFE_EXCEPTION("handleNonRtData");

if (fLastPingTime > 0 && Time::currentTimeMillis() > fLastPingTime + 30000)
{
carla_stderr("Did not receive ping message from server for 30 secs, closing...");
// TODO
//threadShouldExit();
//callback(ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr);
}
}
else if (fInitiated)
{
@@ -447,17 +461,15 @@ public:
portName += ":";
}

if (fInfo.aInNames != nullptr && fInfo.aInNames[j] != nullptr)
if (fInfo.aIns > 1)
{
portName += fInfo.aInNames[j];
}
else if (fInfo.aIns > 1)
{
portName += "input_";
portName += "audio_in_";
portName += CarlaString(j+1);
}
else
portName += "input";
{
portName += "audio_in";
}

portName.truncate(portNameSize);

@@ -476,17 +488,15 @@ public:
portName += ":";
}

if (fInfo.aOutNames != nullptr && fInfo.aOutNames[j] != nullptr)
if (fInfo.aOuts > 1)
{
portName += fInfo.aOutNames[j];
}
else if (fInfo.aOuts > 1)
{
portName += "output_";
portName += "audio_out_";
portName += CarlaString(j+1);
}
else
portName += "output";
{
portName += "audio_out";
}

portName.truncate(portNameSize);

@@ -1097,238 +1107,35 @@ public:
carla_debug("CarlaPluginJack::handleNonRtData() - got opcode: %s", PluginBridgeNonRtServerOpcode2str(opcode));
}
//#endif
if (opcode != kPluginBridgeNonRtServerNull && fLastPongTime > 0)
fLastPongTime = Time::currentTimeMillis();
if (opcode != kPluginBridgeNonRtServerNull && fLastPingTime > 0)
fLastPingTime = Time::currentTimeMillis();

switch (opcode)
{
case kPluginBridgeNonRtServerNull:
case kPluginBridgeNonRtServerPong:
break;

case kPluginBridgeNonRtServerPluginInfo1:
// uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readLong();
break;

case kPluginBridgeNonRtServerPluginInfo2: {
// uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright)

// realName
const uint32_t realNameSize(fShmNonRtServerControl.readUInt());
char realName[realNameSize+1];
carla_zeroChars(realName, realNameSize+1);
fShmNonRtServerControl.readCustomData(realName, realNameSize);

// label
const uint32_t labelSize(fShmNonRtServerControl.readUInt());
char label[labelSize+1];
carla_zeroChars(label, labelSize+1);
fShmNonRtServerControl.readCustomData(label, labelSize);

// maker
const uint32_t makerSize(fShmNonRtServerControl.readUInt());
char maker[makerSize+1];
carla_zeroChars(maker, makerSize+1);
fShmNonRtServerControl.readCustomData(maker, makerSize);

// copyright
const uint32_t copyrightSize(fShmNonRtServerControl.readUInt());
char copyright[copyrightSize+1];
carla_zeroChars(copyright, copyrightSize+1);
fShmNonRtServerControl.readCustomData(copyright, copyrightSize);

fInfo.name = realName;
fInfo.label = label;

if (pData->name == nullptr)
pData->name = pData->engine->getUniquePluginName(realName);
} break;

case kPluginBridgeNonRtServerPluginInfo2:
case kPluginBridgeNonRtServerAudioCount:
// uint/ins, uint/outs
fInfo.aIns = fShmNonRtServerControl.readUInt();
fInfo.aOuts = fShmNonRtServerControl.readUInt();

CARLA_SAFE_ASSERT(fInfo.aInNames == nullptr);
CARLA_SAFE_ASSERT(fInfo.aOutNames == nullptr);

if (fInfo.aIns > 0)
{
fInfo.aInNames = new const char*[fInfo.aIns];
carla_zeroPointers(fInfo.aInNames, fInfo.aIns);
}

if (fInfo.aOuts > 0)
{
fInfo.aOutNames = new const char*[fInfo.aOuts];
carla_zeroPointers(fInfo.aOutNames, fInfo.aOuts);
}
break;

case kPluginBridgeNonRtServerMidiCount:
// uint/ins, uint/outs
fInfo.mIns = fShmNonRtServerControl.readUInt();
fInfo.mOuts = fShmNonRtServerControl.readUInt();
break;

case kPluginBridgeNonRtServerCvCount:
// uint/ins, uint/outs
fInfo.cvIns = fShmNonRtServerControl.readUInt();
fInfo.cvOuts = fShmNonRtServerControl.readUInt();
break;

case kPluginBridgeNonRtServerParameterCount:
// uint/count
fShmNonRtServerControl.readUInt();
break;

case kPluginBridgeNonRtServerProgramCount:
// uint/count
fShmNonRtServerControl.readUInt();
break;

case kPluginBridgeNonRtServerMidiProgramCount:
// uint/count
fShmNonRtServerControl.readUInt();
break;

case kPluginBridgeNonRtServerPortName: {
// byte/type, uint/index, uint/size, str[] (name)
const uint8_t portType = fShmNonRtServerControl.readByte();
const uint32_t index = fShmNonRtServerControl.readUInt();

// name
const uint32_t nameSize(fShmNonRtServerControl.readUInt());
char* const name = new char[nameSize+1];
carla_zeroChars(name, nameSize+1);
fShmNonRtServerControl.readCustomData(name, nameSize);

CARLA_SAFE_ASSERT_BREAK(portType > kPluginBridgePortNull && portType < kPluginBridgePortTypeCount);

switch (portType)
{
case kPluginBridgePortAudioInput:
CARLA_SAFE_ASSERT_BREAK(index < fInfo.aIns);
fInfo.aInNames[index] = name;
break;
case kPluginBridgePortAudioOutput:
CARLA_SAFE_ASSERT_BREAK(index < fInfo.aOuts);
fInfo.aOutNames[index] = name;
break;
}

} break;

case kPluginBridgeNonRtServerPortName:
case kPluginBridgeNonRtServerParameterData1:
// uint/index, int/rindex, uint/type, uint/hints, int/cc
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readInt();
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readShort();
break;

case kPluginBridgeNonRtServerParameterData2:
// uint/index, uint/size, str[] (name), uint/size, str[] (unit)
fShmNonRtServerControl.readUInt();
if (const uint32_t size = fShmNonRtServerControl.readUInt())
{
char name[size];
fShmNonRtServerControl.readCustomData(name, size);
}
if (const uint32_t size = fShmNonRtServerControl.readUInt())
{
char symbol[size];
fShmNonRtServerControl.readCustomData(symbol, size);
}
if (const uint32_t size = fShmNonRtServerControl.readUInt())
{
char unit[size];
fShmNonRtServerControl.readCustomData(unit, size);
}
break;

case kPluginBridgeNonRtServerParameterRanges:
// uint/index, float/def, float/min, float/max, float/step, float/stepSmall, float/stepLarge
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readFloat();
fShmNonRtServerControl.readFloat();
fShmNonRtServerControl.readFloat();
fShmNonRtServerControl.readFloat();
fShmNonRtServerControl.readFloat();
fShmNonRtServerControl.readFloat();
break;

case kPluginBridgeNonRtServerParameterValue:
// uint/index, float/value
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readFloat();
break;

case kPluginBridgeNonRtServerParameterValue2:
// uint/index, float/value
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readFloat();
break;

case kPluginBridgeNonRtServerDefaultValue:
// uint/index, float/value
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readFloat();
break;

case kPluginBridgeNonRtServerCurrentProgram:
// int/index
fShmNonRtServerControl.readInt();
case kPluginBridgeNonRtServerCurrentMidiProgram:
case kPluginBridgeNonRtServerProgramName:
case kPluginBridgeNonRtServerMidiProgramData:
case kPluginBridgeNonRtServerSetCustomData:
break;

case kPluginBridgeNonRtServerCurrentMidiProgram: {
// int/index
fShmNonRtServerControl.readInt();
} break;

case kPluginBridgeNonRtServerProgramName: {
// uint/index, uint/size, str[] (name)
fShmNonRtServerControl.readUInt();
const uint32_t nameSize(fShmNonRtServerControl.readUInt());
char name[nameSize];
fShmNonRtServerControl.readCustomData(name, nameSize);
} break;

case kPluginBridgeNonRtServerMidiProgramData: {
// uint/index, uint/bank, uint/program, uint/size, str[] (name)
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readUInt();
fShmNonRtServerControl.readUInt();
const uint32_t nameSize(fShmNonRtServerControl.readUInt());
char name[nameSize];
fShmNonRtServerControl.readCustomData(name, nameSize);
} break;

case kPluginBridgeNonRtServerSetCustomData: {
// uint/size, str[], uint/size, str[], uint/size, str[]

// type
const uint32_t typeSize(fShmNonRtServerControl.readUInt());
char type[typeSize];
fShmNonRtServerControl.readCustomData(type, typeSize);

// key
const uint32_t keySize(fShmNonRtServerControl.readUInt());
char key[keySize];
fShmNonRtServerControl.readCustomData(key, keySize);

// value
const uint32_t valueSize(fShmNonRtServerControl.readUInt());
char value[valueSize];
fShmNonRtServerControl.readCustomData(value, valueSize);
} break;

case kPluginBridgeNonRtServerSetChunkDataFile: {
// uint/size, str[] (filename)
const uint32_t chunkFilePathSize(fShmNonRtServerControl.readUInt());
@@ -1337,8 +1144,6 @@ public:
} break;

case kPluginBridgeNonRtServerSetLatency:
// uint
fShmNonRtServerControl.readUInt();
break;

case kPluginBridgeNonRtServerReady:
@@ -1397,7 +1202,7 @@ public:

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

bool init(const char* const filename, const char* const name)
bool init(const char* const filename, const char* const name, const char* const label)
{
CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);

@@ -1410,16 +1215,52 @@ public:
return false;
}

if (filename == nullptr || filename[0] == '\0')
{
pData->engine->setLastError("null filename");
return false;
}

if (label == nullptr || label[0] == '\0')
{
pData->engine->setLastError("null label");
return false;
}

// ---------------------------------------------------------------
// check setup

if (std::strlen(label) != 6)
{
pData->engine->setLastError("invalid application setup received");
return false;
}

for (int i=6; --i >= 0;) {
CARLA_SAFE_ASSERT_RETURN(label[i] >= '0' && label[i] < '0'+64, false);
}

fInfo.aIns = label[0] - '0';
fInfo.aOuts = label[1] - '0';
fInfo.cvIns = label[2] - '0';
fInfo.cvOuts = label[3] - '0';
fInfo.mIns = label[4] - '0';
fInfo.mOuts = label[5] - '0';

fInfo.setupLabel = label;

// TODO
fInfo.cvIns = fInfo.cvOuts = fInfo.mIns = fInfo.mOuts = 0;

// ---------------------------------------------------------------
// set info

pData->filename = carla_strdup(filename);

if (name != nullptr && name[0] != '\0')
pData->name = pData->engine->getUniquePluginName(name);

if (filename != nullptr && filename[0] != '\0')
pData->filename = carla_strdup(filename);
else
pData->filename = carla_strdup("");
pData->name = pData->engine->getUniquePluginName("Jack Application");

std::srand(static_cast<uint>(std::time(nullptr)));

@@ -1457,8 +1298,8 @@ public:
}

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

// init bridge thread

{
char shmIdsStr[6*4+1];
carla_zeroChars(shmIdsStr, 6*4+1);
@@ -1468,7 +1309,7 @@ public:
std::strncpy(shmIdsStr+6*2, &fShmNonRtClientControl.filename[fShmNonRtClientControl.filename.length()-6], 6);
std::strncpy(shmIdsStr+6*3, &fShmNonRtServerControl.filename[fShmNonRtServerControl.filename.length()-6], 6);

fBridgeThread.setData(shmIdsStr);
fBridgeThread.setData(shmIdsStr, label);
}

if (! restartBridgeThread())
@@ -1499,7 +1340,7 @@ private:
bool fProcCanceled;
uint fProcWaitTime;

int64_t fLastPongTime;
int64_t fLastPingTime;

CarlaPluginJackThread fBridgeThread;

@@ -1514,10 +1355,7 @@ private:
uint32_t mIns, mOuts;
PluginCategory category;
uint optionsAvailable;
CarlaString name;
CarlaString label;
const char** aInNames;
const char** aOutNames;
CarlaString setupLabel;
std::vector<uint8_t> chunk;

Info()
@@ -1529,10 +1367,7 @@ private:
mOuts(0),
category(PLUGIN_CATEGORY_NONE),
optionsAvailable(0),
name(),
label(),
aInNames(nullptr),
aOutNames(nullptr),
setupLabel(),
chunk() {}

CARLA_DECLARE_NON_COPY_STRUCT(Info)
@@ -1567,13 +1402,6 @@ private:
fInitError = false;
fTimedError = false;

// cleanup of previous data
delete[] fInfo.aInNames;
fInfo.aInNames = nullptr;

delete[] fInfo.aOutNames;
fInfo.aOutNames = nullptr;

// reset memory
fProcCanceled = false;
fShmRtClientControl.data->procFlags = 0;
@@ -1613,8 +1441,8 @@ private:

fBridgeThread.startThread();

fLastPongTime = Time::currentTimeMillis();
CARLA_SAFE_ASSERT(fLastPongTime > 0);
fLastPingTime = Time::currentTimeMillis();
CARLA_SAFE_ASSERT(fLastPingTime > 0);

static bool sFirstInit = true;

@@ -1626,7 +1454,7 @@ private:

const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin;

for (; Time::currentTimeMillis() < fLastPongTime + timeoutEnd && fBridgeThread.isThreadRunning();)
for (; Time::currentTimeMillis() < fLastPingTime + timeoutEnd && fBridgeThread.isThreadRunning();)
{
pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);

@@ -1643,7 +1471,7 @@ private:
carla_msleep(20);
}

fLastPongTime = -1;
fLastPingTime = -1;

if (fInitError || ! fInitiated)
{
@@ -1677,7 +1505,7 @@ CarlaPlugin* CarlaPlugin::newJackApp(const Initializer& init)
#ifdef CARLA_OS_LINUX
CarlaPluginJack* const plugin(new CarlaPluginJack(init.engine, init.id));

if (! plugin->init(init.filename, init.name))
if (! plugin->init(init.filename, init.name, init.label))
{
delete plugin;
return nullptr;


+ 12
- 1
source/carla_database.py View File

@@ -1896,7 +1896,18 @@ class JackApplicationW(QDialog):
self.host = host

def getCommandAndFlags(self):
return (self.ui.le_command.text(), self.ui.le_flags.text())
name = self.ui.le_name.text()
command = self.ui.le_command.text()
if not name:
name = command.split(" ",1)[0]
baseIntVal = ord('0')
labelSetup = "%s%s%s%s%s%s" % (chr(baseIntVal+self.ui.sb_audio_ins.value()),
chr(baseIntVal+self.ui.sb_audio_outs.value()),
chr(baseIntVal+self.ui.sb_cv_ins.value()),
chr(baseIntVal+self.ui.sb_cv_outs.value()),
chr(baseIntVal+self.ui.sb_midi_ins.value()),
chr(baseIntVal+self.ui.sb_midi_outs.value()))
return (command, name, labelSetup)

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



+ 7
- 2
source/carla_host.py View File

@@ -962,9 +962,14 @@ class HostWindow(QMainWindow):
if data is None:
return

filename, label = data
filename, name, label = data

if not self.host.add_plugin(BINARY_NATIVE, PLUGIN_JACK, filename, None, label, 0, None, 0x0):
if not filename:
CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Cannot add jack application"),
self.tr("command is empty"), QMessageBox.Ok, QMessageBox.Ok)
return

if not self.host.add_plugin(BINARY_NATIVE, PLUGIN_JACK, filename, name, label, 0, None, 0x0):
CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to load plugin"),
self.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok)



+ 56
- 161
source/libjack/libjack.cpp View File

@@ -39,15 +39,20 @@ public:
fServer(),
fIsValid(false),
fIsOffline(false),
fLastPingTime(-1),
fAudioIns(0),
fAudioOuts(0)
fLastPingTime(-1)
{
carla_debug("CarlaJackAppClient::CarlaJackAppClient()");

const char* const shmIds(std::getenv("CARLA_SHM_IDS"));
CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && std::strlen(shmIds) == 6*4,);

const char* const numPortsStr(std::getenv("CARLA_NUM_PORTS"));
CARLA_SAFE_ASSERT_RETURN(numPortsStr != nullptr && std::strlen(numPortsStr) == 3*2,);

for (int i=6; --i >= 0;) {
CARLA_SAFE_ASSERT_RETURN(numPortsStr[i] >= '0' && numPortsStr[i] < '0'+64,);
}

std::memcpy(fBaseNameAudioPool, shmIds+6*0, 6);
std::memcpy(fBaseNameRtClientControl, shmIds+6*1, 6);
std::memcpy(fBaseNameNonRtClientControl, shmIds+6*2, 6);
@@ -58,6 +63,13 @@ public:
fBaseNameNonRtClientControl[6] = '\0';
fBaseNameNonRtServerControl[6] = '\0';

fNumPorts.audioIns = numPortsStr[0] - '0';
fNumPorts.audioOuts = numPortsStr[1] - '0';
fNumPorts.cvIns = numPortsStr[2] - '0';
fNumPorts.cvOuts = numPortsStr[3] - '0';
fNumPorts.midiIns = numPortsStr[4] - '0';
fNumPorts.midiOuts = numPortsStr[5] - '0';

startThread(10);
}

@@ -65,7 +77,6 @@ public:
{
carla_debug("CarlaJackAppClient::~CarlaJackAppClient()");

carla_debug("CarlaEnginePlugin::close()");
fLastPingTime = -1;

stopThread(5000);
@@ -84,12 +95,6 @@ public:
fClients.clear();
}

void clear() noexcept;
bool isValid() const noexcept;

void activate();
void handleNonRtData();

JackClientState* addClient(const char* const name)
{
JackClientState* const jclient(new JackClientState(fServer, name));
@@ -110,6 +115,11 @@ public:
return true;
}

void clear() noexcept;
bool isValid() const noexcept;

void handleNonRtData();

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

protected:
@@ -130,8 +140,22 @@ private:
bool fIsOffline;
int64_t fLastPingTime;

uint32_t fAudioIns;
uint32_t fAudioOuts;
struct NumPorts {
uint32_t audioIns;
uint32_t audioOuts;
uint32_t cvIns;
uint32_t cvOuts;
uint32_t midiIns;
uint32_t midiOuts;

NumPorts()
: audioIns(0),
audioOuts(0),
cvIns(0),
cvOuts(0),
midiIns(0),
midiOuts(0) {}
} fNumPorts;

CarlaMutex fRealtimeThreadMutex;

@@ -153,140 +177,6 @@ bool CarlaJackAppClient::isValid() const noexcept
return fIsValid;
}

void CarlaJackAppClient::activate()
{
const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);

{
fLastPingTime = Time::currentTimeMillis();
CARLA_SAFE_ASSERT(fLastPingTime > 0);

char bufStr[STR_MAX+1];
uint32_t bufStrSize;

// kPluginBridgeNonRtServerPluginInfo1
{
// uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPluginInfo1);
fShmNonRtServerControl.writeUInt(PLUGIN_CATEGORY_NONE);
fShmNonRtServerControl.writeUInt(0x0);
fShmNonRtServerControl.writeUInt(0x0);
fShmNonRtServerControl.writeUInt(0x0);
fShmNonRtServerControl.writeLong(0);
fShmNonRtServerControl.commitWrite();
}

// kPluginBridgeNonRtServerPluginInfo2
{
// uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright)
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPluginInfo2);

carla_zeroChars(bufStr, STR_MAX);
std::strncpy(bufStr, "Jack App", 64);
bufStrSize = carla_fixedValue(1U, 64U, static_cast<uint32_t>(std::strlen(bufStr)));
fShmNonRtServerControl.writeUInt(bufStrSize);
fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);

carla_zeroChars(bufStr, STR_MAX);

bufStrSize = 1;
fShmNonRtServerControl.writeUInt(bufStrSize);
fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);

fShmNonRtServerControl.writeUInt(bufStrSize);
fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);

fShmNonRtServerControl.writeUInt(bufStrSize);
fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);

fShmNonRtServerControl.commitWrite();
}

// kPluginBridgeNonRtServerAudioCount
{
const uint32_t aIns = 2; //fClient.audioIns.count();
const uint32_t aOuts = 2; //fClient.audioOuts.count();

// uint/ins, uint/outs
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerAudioCount);
fShmNonRtServerControl.writeUInt(aIns);
fShmNonRtServerControl.writeUInt(aOuts);
fShmNonRtServerControl.commitWrite();


// kPluginBridgeNonRtServerPortName
for (uint32_t i=0; i<aIns; ++i)
{
//const JackPortState* const jport(fClient.audioIns.getAt(i, nullptr));
//CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);

//const char* const portName(jport->name);
//CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0');

std::snprintf(bufStr, 64, "in_%i", i+1);

// byte/type, uint/index, uint/size, str[] (name)
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPortName);
fShmNonRtServerControl.writeByte(kPluginBridgePortAudioInput);
fShmNonRtServerControl.writeUInt(i);

bufStrSize = static_cast<uint32_t>(std::strlen(bufStr));
fShmNonRtServerControl.writeUInt(bufStrSize);
fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
}

// kPluginBridgeNonRtServerPortName
for (uint32_t i=0; i<aOuts; ++i)
{
//const JackPortState* const jport(fClient.audioOuts.getAt(i, nullptr));
//CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);

//const char* const portName(jport->name);
//CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0');

std::snprintf(bufStr, 64, "out_%i", i+1);

// byte/type, uint/index, uint/size, str[] (name)
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPortName);
fShmNonRtServerControl.writeByte(kPluginBridgePortAudioOutput);
fShmNonRtServerControl.writeUInt(i);

bufStrSize = static_cast<uint32_t>(std::strlen(bufStr));
fShmNonRtServerControl.writeUInt(bufStrSize);
fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
}
}

fShmNonRtServerControl.waitIfDataIsReachingLimit();

// kPluginBridgeNonRtServerMidiCount
{
const uint32_t mIns = 0; // fClient.midiIns.count();
const uint32_t mOuts = 0; // fClient.midiOuts.count();

// uint/ins, uint/outs
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerMidiCount);
fShmNonRtServerControl.writeUInt(mIns);
fShmNonRtServerControl.writeUInt(mOuts);
fShmNonRtServerControl.commitWrite();
}

fShmNonRtServerControl.waitIfDataIsReachingLimit();

// ready!
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerReady);
fShmNonRtServerControl.commitWrite();
fShmNonRtServerControl.waitIfDataIsReachingLimit();

// must be static
fAudioIns = 2; //fClient.audioIns.count();
fAudioOuts = 2; //fClient.audioOuts.count();

carla_stdout("Carla Jack Client Ready!");
fLastPingTime = Time::currentTimeMillis();
}
}

void CarlaJackAppClient::handleNonRtData()
{
for (; fShmNonRtClientControl.isDataAvailableForReading();)
@@ -485,13 +375,18 @@ void CarlaJackAppClient::run()
{
const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);

fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong);
fLastPingTime = Time::currentTimeMillis();
CARLA_SAFE_ASSERT(fLastPingTime > 0);

// ready!
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerReady);
fShmNonRtServerControl.commitWrite();
fShmNonRtServerControl.waitIfDataIsReachingLimit();
}

fIsValid = true;
activate();
fLastPingTime = Time::currentTimeMillis();
carla_stdout("Carla Jack Client Ready!");

#ifdef __SSE2_MATH__
// Set FTZ and DAZ flags
@@ -591,11 +486,11 @@ void CarlaJackAppClient::run()

if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated)
{
if (fAudioIns > 0)
fdata += fServer.bufferSize*fAudioIns;
if (fNumPorts.audioIns > 0)
fdata += fServer.bufferSize*fNumPorts.audioIns;

if (fAudioOuts > 0)
carla_zeroFloats(fdata, fServer.bufferSize*fAudioOuts);
if (fNumPorts.audioOuts > 0)
carla_zeroFloats(fdata, fServer.bufferSize*fNumPorts.audioOuts);

if (jclient->deactivated)
{
@@ -609,23 +504,23 @@ void CarlaJackAppClient::run()
i = 0;
for (LinkedList<JackPortState*>::Itenerator it = jclient->audioIns.begin2(); it.valid(); it.next())
{
CARLA_SAFE_ASSERT_BREAK(i++ < fAudioIns);
CARLA_SAFE_ASSERT_BREAK(i++ < fNumPorts.audioIns);
if (JackPortState* const jport = it.getValue(nullptr))
jport->buffer = fdata;
fdata += fServer.bufferSize;
}
for (; i++ < fAudioIns;)
for (; i++ < fNumPorts.audioIns;)
fdata += fServer.bufferSize;

i = 0;
for (LinkedList<JackPortState*>::Itenerator it = jclient->audioOuts.begin2(); it.valid(); it.next())
{
CARLA_SAFE_ASSERT_BREAK(i++ < fAudioOuts);
CARLA_SAFE_ASSERT_BREAK(i++ < fNumPorts.audioOuts);
if (JackPortState* const jport = it.getValue(nullptr))
jport->buffer = fdata;
fdata += fServer.bufferSize;
}
for (; i++ < fAudioOuts;)
for (; i++ < fNumPorts.audioOuts;)
{
carla_zeroFloats(fdata, fServer.bufferSize);
fdata += fServer.bufferSize;
@@ -637,11 +532,11 @@ void CarlaJackAppClient::run()
}
else
{
if (fAudioIns > 0)
fdata += fServer.bufferSize*fAudioIns;
if (fNumPorts.audioIns > 0)
fdata += fServer.bufferSize*fNumPorts.audioIns;

if (fAudioOuts > 0)
carla_zeroFloats(fdata, fServer.bufferSize*fAudioOuts);
if (fNumPorts.audioOuts > 0)
carla_zeroFloats(fdata, fServer.bufferSize*fNumPorts.audioOuts);
}
}
else


+ 2
- 1
source/utils/CarlaStateUtils.cpp View File

@@ -301,7 +301,7 @@ bool CarlaStateSave::fillFromXmlElement(const XmlElement* const xmlElement)
type = xmlSafeStringCharDup(text, false);
else if (tag.equalsIgnoreCase("name"))
name = xmlSafeStringCharDup(text, false);
else if (tag.equalsIgnoreCase("label") || tag.equalsIgnoreCase("identifier") || tag.equalsIgnoreCase("uri"))
else if (tag.equalsIgnoreCase("label") || tag.equalsIgnoreCase("identifier") || tag.equalsIgnoreCase("uri") || tag.equalsIgnoreCase("setup"))
label = xmlSafeStringCharDup(text, false);
else if (tag.equalsIgnoreCase("binary") || tag.equalsIgnoreCase("bundle") || tag.equalsIgnoreCase("filename"))
binary = xmlSafeStringCharDup(text, false);
@@ -539,6 +539,7 @@ void CarlaStateSave::dumpToMemoryStream(MemoryOutputStream& content) const
break;
case PLUGIN_JACK:
infoXml << " <Filename>" << xmlSafeString(binary, true) << "</Filename>\n";
infoXml << " <Setup>" << xmlSafeString(label, true) << "</Setup>\n";
break;
}



Loading…
Cancel
Save