| @@ -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"> | |||
| @@ -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; | |||
| @@ -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) | |||
| # -------------------------------------------------------------------------------------------------------- | |||
| @@ -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) | |||
| @@ -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 | |||
| @@ -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; | |||
| } | |||