Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2082 lines
68KB

  1. /*
  2. * Carla Native Plugin
  3. * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the GPL.txt file
  16. */
  17. #include "CarlaPluginInternal.hpp"
  18. #ifdef WANT_NATIVE
  19. #include "CarlaNative.h"
  20. #include <QtGui/QFileDialog>
  21. CARLA_BACKEND_START_NAMESPACE
  22. struct NativePluginMidiData {
  23. uint32_t count;
  24. uint32_t* indexes;
  25. CarlaEngineEventPort** ports;
  26. NativePluginMidiData()
  27. : count(0),
  28. indexes(nullptr),
  29. ports(nullptr) {}
  30. void createNew(const uint32_t count)
  31. {
  32. CARLA_ASSERT(ports == nullptr);
  33. CARLA_ASSERT(indexes == nullptr);
  34. if (ports == nullptr)
  35. {
  36. ports = new CarlaEngineEventPort*[count];
  37. for (uint32_t i=0; i < count; i++)
  38. ports[i] = nullptr;
  39. }
  40. if (indexes == nullptr)
  41. {
  42. indexes = new uint32_t[count];
  43. for (uint32_t i=0; i < count; i++)
  44. indexes[i] = 0;
  45. }
  46. this->count = count;
  47. }
  48. void clear()
  49. {
  50. if (ports != nullptr)
  51. {
  52. for (uint32_t i=0; i < count; i++)
  53. {
  54. if (ports[i] != nullptr)
  55. {
  56. delete ports[i];
  57. ports[i] = nullptr;
  58. }
  59. }
  60. delete[] ports;
  61. ports = nullptr;
  62. }
  63. if (indexes != nullptr)
  64. {
  65. delete[] indexes;
  66. indexes = nullptr;
  67. }
  68. count = 0;
  69. }
  70. void initBuffers(CarlaEngine* const engine)
  71. {
  72. for (uint32_t i=0; i < count; i++)
  73. {
  74. if (ports[i] != nullptr)
  75. ports[i]->initBuffer(engine);
  76. }
  77. }
  78. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(NativePluginMidiData)
  79. };
  80. class NativePlugin : public CarlaPlugin
  81. {
  82. public:
  83. NativePlugin(CarlaEngine* const engine, const unsigned int id)
  84. : CarlaPlugin(engine, id),
  85. fHandle(nullptr),
  86. fHandle2(nullptr),
  87. fDescriptor(nullptr),
  88. fIsProcessing(false),
  89. fIsUiVisible(false),
  90. fAudioInBuffers(nullptr),
  91. fAudioOutBuffers(nullptr),
  92. fMidiEventCount(0)
  93. {
  94. carla_debug("NativePlugin::NativePlugin(%p, %i)", engine, id);
  95. fHost.handle = this;
  96. fHost.get_buffer_size = carla_host_get_buffer_size;
  97. fHost.get_sample_rate = carla_host_get_sample_rate;
  98. fHost.get_time_info = carla_host_get_time_info;
  99. fHost.write_midi_event = carla_host_write_midi_event;
  100. fHost.ui_parameter_changed = carla_host_ui_parameter_changed;
  101. fHost.ui_custom_data_changed = carla_host_ui_custom_data_changed;
  102. fHost.ui_closed = carla_host_ui_closed;
  103. fHost.ui_open_file = carla_host_ui_open_file;
  104. fHost.ui_save_file = carla_host_ui_save_file;
  105. carla_zeroMem(fMidiEvents, sizeof(::MidiEvent)*MAX_MIDI_EVENTS*2);
  106. }
  107. ~NativePlugin()
  108. {
  109. carla_debug("NativePlugin::~NativePlugin()");
  110. if (fDescriptor != nullptr)
  111. {
  112. if (fDescriptor->ui_show != nullptr && fIsUiVisible)
  113. fDescriptor->ui_show(fHandle, false);
  114. if (fDescriptor->deactivate != nullptr && kData->activeBefore)
  115. {
  116. if (fHandle != nullptr)
  117. fDescriptor->deactivate(fHandle);
  118. if (fHandle2 != nullptr)
  119. fDescriptor->deactivate(fHandle2);
  120. }
  121. if (fDescriptor->cleanup != nullptr)
  122. {
  123. if (fHandle != nullptr)
  124. fDescriptor->cleanup(fHandle);
  125. if (fHandle2 != nullptr)
  126. fDescriptor->cleanup(fHandle2);
  127. }
  128. fHandle = nullptr;
  129. fHandle2 = nullptr;
  130. fDescriptor = nullptr;
  131. }
  132. deleteBuffers();
  133. }
  134. // -------------------------------------------------------------------
  135. // Information (base)
  136. PluginType type() const
  137. {
  138. return PLUGIN_INTERNAL;
  139. }
  140. PluginCategory category() const
  141. {
  142. CARLA_ASSERT(fDescriptor != nullptr);
  143. if (fDescriptor != nullptr)
  144. return static_cast<PluginCategory>(fDescriptor->category);
  145. return getPluginCategoryFromName(fName);
  146. }
  147. // -------------------------------------------------------------------
  148. // Information (count)
  149. uint32_t midiInCount()
  150. {
  151. return fMidiIn.count;
  152. }
  153. uint32_t midiOutCount()
  154. {
  155. return fMidiOut.count;
  156. }
  157. uint32_t parameterScalePointCount(const uint32_t parameterId) const
  158. {
  159. CARLA_ASSERT(fDescriptor != nullptr);
  160. CARLA_ASSERT(fHandle != nullptr);
  161. CARLA_ASSERT(parameterId < kData->param.count);
  162. if (fDescriptor != nullptr && fHandle != nullptr && parameterId < kData->param.count && fDescriptor->get_parameter_info != nullptr)
  163. {
  164. if (const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId))
  165. return param->scalePointCount;
  166. }
  167. return 0;
  168. }
  169. // -------------------------------------------------------------------
  170. // Information (per-plugin data)
  171. unsigned int availableOptions()
  172. {
  173. CARLA_ASSERT(fDescriptor != nullptr);
  174. unsigned int options = 0x0;
  175. if (fDescriptor->name != nullptr)
  176. {
  177. if (std::strcmp(fDescriptor->name, "ZynAddSubFX") == 0)
  178. {
  179. // nothing
  180. }
  181. else
  182. {
  183. options |= PLUGIN_OPTION_FIXED_BUFFER;
  184. }
  185. }
  186. options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  187. //if ((kData->audioIns.count() == 1 || kData->audioOuts.count() == 0) || (kData->audioIns.count() == 0 || kData->audioOuts.count() == 1))
  188. // options |= PLUGIN_OPTION_FORCE_STEREO;
  189. if (fMidiIn.count > 0)
  190. {
  191. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  192. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  193. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  194. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  195. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  196. }
  197. return options;
  198. }
  199. float getParameterValue(const uint32_t parameterId)
  200. {
  201. CARLA_ASSERT(fDescriptor != nullptr);
  202. CARLA_ASSERT(fHandle != nullptr);
  203. CARLA_ASSERT(parameterId < kData->param.count);
  204. if (fDescriptor != nullptr && fHandle != nullptr && parameterId < kData->param.count && fDescriptor->get_parameter_value != nullptr)
  205. return fDescriptor->get_parameter_value(fHandle, parameterId);
  206. return 0.0f;
  207. }
  208. float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId)
  209. {
  210. CARLA_ASSERT(fDescriptor != nullptr);
  211. CARLA_ASSERT(fHandle != nullptr);
  212. CARLA_ASSERT(parameterId < kData->param.count);
  213. CARLA_ASSERT(scalePointId < parameterScalePointCount(parameterId));
  214. if (fDescriptor != nullptr && fHandle != nullptr && parameterId < kData->param.count && fDescriptor->get_parameter_info != nullptr)
  215. {
  216. if (const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId))
  217. {
  218. const ParameterScalePoint& scalePoint = param->scalePoints[scalePointId];
  219. return scalePoint.value;
  220. }
  221. }
  222. return 0.0f;
  223. }
  224. void getLabel(char* const strBuf)
  225. {
  226. CARLA_ASSERT(fDescriptor != nullptr);
  227. if (fDescriptor != nullptr && fDescriptor->label != nullptr)
  228. std::strncpy(strBuf, fDescriptor->label, STR_MAX);
  229. else
  230. CarlaPlugin::getLabel(strBuf);
  231. }
  232. void getMaker(char* const strBuf)
  233. {
  234. CARLA_ASSERT(fDescriptor != nullptr);
  235. if (fDescriptor != nullptr && fDescriptor->maker != nullptr)
  236. std::strncpy(strBuf, fDescriptor->maker, STR_MAX);
  237. else
  238. CarlaPlugin::getMaker(strBuf);
  239. }
  240. void getCopyright(char* const strBuf)
  241. {
  242. CARLA_ASSERT(fDescriptor != nullptr);
  243. if (fDescriptor != nullptr && fDescriptor->copyright != nullptr)
  244. std::strncpy(strBuf, fDescriptor->copyright, STR_MAX);
  245. else
  246. CarlaPlugin::getCopyright(strBuf);
  247. }
  248. void getRealName(char* const strBuf)
  249. {
  250. CARLA_ASSERT(fDescriptor != nullptr);
  251. if (fDescriptor != nullptr && fDescriptor->name != nullptr)
  252. std::strncpy(strBuf, fDescriptor->name, STR_MAX);
  253. else
  254. CarlaPlugin::getRealName(strBuf);
  255. }
  256. void getParameterName(const uint32_t parameterId, char* const strBuf)
  257. {
  258. CARLA_ASSERT(fDescriptor != nullptr);
  259. CARLA_ASSERT(fHandle != nullptr);
  260. CARLA_ASSERT(parameterId < kData->param.count);
  261. if (fDescriptor != nullptr && fHandle != nullptr && parameterId < kData->param.count && fDescriptor->get_parameter_info != nullptr)
  262. {
  263. const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId);
  264. if (param != nullptr && param->name != nullptr)
  265. {
  266. std::strncpy(strBuf, param->name, STR_MAX);
  267. return;
  268. }
  269. }
  270. CarlaPlugin::getParameterName(parameterId, strBuf);
  271. }
  272. void getParameterText(const uint32_t parameterId, char* const strBuf)
  273. {
  274. CARLA_ASSERT(fDescriptor != nullptr);
  275. CARLA_ASSERT(fHandle != nullptr);
  276. CARLA_ASSERT(parameterId < kData->param.count);
  277. if (fDescriptor != nullptr && fHandle != nullptr && parameterId < kData->param.count && fDescriptor->get_parameter_text != nullptr)
  278. {
  279. if (const char* const text = fDescriptor->get_parameter_text(fHandle, parameterId))
  280. {
  281. std::strncpy(strBuf, text, STR_MAX);
  282. return;
  283. }
  284. }
  285. CarlaPlugin::getParameterText(parameterId, strBuf);
  286. }
  287. void getParameterUnit(const uint32_t parameterId, char* const strBuf)
  288. {
  289. CARLA_ASSERT(fDescriptor != nullptr);
  290. CARLA_ASSERT(fHandle != nullptr);
  291. CARLA_ASSERT(parameterId < kData->param.count);
  292. if (fDescriptor != nullptr && fHandle != nullptr && parameterId < kData->param.count && fDescriptor->get_parameter_info != nullptr)
  293. {
  294. const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId);
  295. if (param != nullptr && param->unit != nullptr)
  296. {
  297. std::strncpy(strBuf, param->unit, STR_MAX);
  298. return;
  299. }
  300. }
  301. CarlaPlugin::getParameterUnit(parameterId, strBuf);
  302. }
  303. void getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf)
  304. {
  305. CARLA_ASSERT(fDescriptor != nullptr);
  306. CARLA_ASSERT(fHandle != nullptr);
  307. CARLA_ASSERT(parameterId < kData->param.count);
  308. CARLA_ASSERT(scalePointId < parameterScalePointCount(parameterId));
  309. if (fDescriptor != nullptr && fHandle != nullptr && parameterId < kData->param.count && fDescriptor->get_parameter_info != nullptr)
  310. {
  311. if (const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId))
  312. {
  313. const ParameterScalePoint& scalePoint = param->scalePoints[scalePointId];
  314. if (scalePoint.label != nullptr)
  315. {
  316. std::strncpy(strBuf, scalePoint.label, STR_MAX);
  317. return;
  318. }
  319. }
  320. }
  321. CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf);
  322. }
  323. // -------------------------------------------------------------------
  324. // Set data (plugin-specific stuff)
  325. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback)
  326. {
  327. CARLA_ASSERT(fDescriptor != nullptr);
  328. CARLA_ASSERT(fHandle != nullptr);
  329. CARLA_ASSERT(parameterId < kData->param.count);
  330. const float fixedValue = kData->param.fixValue(parameterId, value);
  331. if (fDescriptor != nullptr && fHandle != nullptr && parameterId < kData->param.count && fDescriptor->set_parameter_value != nullptr)
  332. {
  333. fDescriptor->set_parameter_value(fHandle, parameterId, fixedValue);
  334. if (fHandle2 != nullptr)
  335. fDescriptor->set_parameter_value(fHandle2, parameterId, fixedValue);
  336. }
  337. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  338. }
  339. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui)
  340. {
  341. CARLA_ASSERT(fDescriptor != nullptr);
  342. CARLA_ASSERT(fHandle != nullptr);
  343. CARLA_ASSERT(type != nullptr);
  344. CARLA_ASSERT(key != nullptr);
  345. CARLA_ASSERT(value != nullptr);
  346. if (type == nullptr)
  347. return carla_stderr2("NativePlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));
  348. if (std::strcmp(type, CUSTOM_DATA_STRING) != 0)
  349. return carla_stderr2("NativePlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));
  350. if (key == nullptr)
  351. return carla_stderr2("NativePlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - key is null", type, key, value, bool2str(sendGui));
  352. if (value == nullptr)
  353. return carla_stderr2("Nativelugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - value is null", type, key, value, bool2str(sendGui));
  354. if (fDescriptor != nullptr && fHandle != nullptr)
  355. {
  356. if (fDescriptor->set_custom_data != nullptr)
  357. {
  358. fDescriptor->set_custom_data(fHandle, key, value);
  359. if (fHandle2)
  360. fDescriptor->set_custom_data(fHandle2, key, value);
  361. }
  362. if (sendGui && fDescriptor->ui_set_custom_data != nullptr)
  363. fDescriptor->ui_set_custom_data(fHandle, key, value);
  364. }
  365. CarlaPlugin::setCustomData(type, key, value, sendGui);
  366. }
  367. void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback)
  368. {
  369. CARLA_ASSERT(fDescriptor != nullptr);
  370. CARLA_ASSERT(fHandle != nullptr);
  371. CARLA_ASSERT(index >= -1 && index < static_cast<int32_t>(kData->midiprog.count));
  372. if (index < -1)
  373. index = -1;
  374. else if (index > static_cast<int32_t>(kData->midiprog.count))
  375. return;
  376. if (fDescriptor != nullptr && fHandle != nullptr && index >= 0)
  377. {
  378. const uint32_t bank = kData->midiprog.data[index].bank;
  379. const uint32_t program = kData->midiprog.data[index].program;
  380. const ScopedProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
  381. fDescriptor->set_midi_program(fHandle, bank, program);
  382. if (fHandle2 != nullptr)
  383. fDescriptor->set_midi_program(fHandle2, bank, program);
  384. }
  385. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
  386. }
  387. // -------------------------------------------------------------------
  388. // Set gui stuff
  389. void showGui(const bool yesNo)
  390. {
  391. CARLA_ASSERT(fDescriptor != nullptr);
  392. CARLA_ASSERT(fHandle != nullptr);
  393. if (fDescriptor != nullptr && fHandle != nullptr && fDescriptor->ui_show != nullptr)
  394. {
  395. fDescriptor->ui_show(fHandle, yesNo);
  396. if (yesNo)
  397. {
  398. // Update UI values, FIXME
  399. if (kData->midiprog.current >= 0)
  400. {
  401. const MidiProgramData& mpData = kData->midiprog.getCurrent();
  402. fDescriptor->ui_set_midi_program(fHandle, mpData.bank, mpData.program);
  403. }
  404. for (uint32_t i=0; i < kData->param.count; i++)
  405. {
  406. fDescriptor->ui_set_parameter_value(fHandle, i, fDescriptor->get_parameter_value(fHandle, i));
  407. }
  408. }
  409. }
  410. fIsUiVisible = yesNo;
  411. }
  412. void idleGui()
  413. {
  414. CARLA_ASSERT(fDescriptor != nullptr);
  415. CARLA_ASSERT(fHandle != nullptr);
  416. if (fIsUiVisible && fDescriptor != nullptr && fHandle != nullptr && fDescriptor->ui_idle != nullptr)
  417. fDescriptor->ui_idle(fHandle);
  418. }
  419. // -------------------------------------------------------------------
  420. // Plugin state
  421. void reload()
  422. {
  423. carla_debug("NativePlugin::reload() - start");
  424. CARLA_ASSERT(kData->engine != nullptr);
  425. CARLA_ASSERT(fDescriptor != nullptr);
  426. CARLA_ASSERT(fHandle != nullptr);
  427. const ProcessMode processMode(kData->engine->getProccessMode());
  428. // Safely disable plugin for reload
  429. const ScopedDisabler sd(this);
  430. deleteBuffers();
  431. const float sampleRate = (float)kData->engine->getSampleRate();
  432. uint32_t aIns, aOuts, mIns, mOuts, params, j;
  433. bool forcedStereoIn, forcedStereoOut;
  434. forcedStereoIn = forcedStereoOut = false;
  435. bool needsCtrlIn, needsCtrlOut;
  436. needsCtrlIn = needsCtrlOut = false;
  437. aIns = fDescriptor->audioIns;
  438. aOuts = fDescriptor->audioOuts;
  439. mIns = fDescriptor->midiIns;
  440. mOuts = fDescriptor->midiOuts;
  441. params = (fDescriptor->get_parameter_count != nullptr && fDescriptor->get_parameter_info != nullptr) ? fDescriptor->get_parameter_count(fHandle) : 0;
  442. if ((fOptions & PLUGIN_OPTION_FORCE_STEREO) != 0 && (aIns == 1 || aOuts == 1) && mIns <= 1 && mOuts <= 1)
  443. {
  444. if (fHandle2 == nullptr)
  445. fHandle2 = fDescriptor->instantiate(fDescriptor, &fHost);
  446. if (aIns == 1)
  447. {
  448. aIns = 2;
  449. forcedStereoIn = true;
  450. }
  451. if (aOuts == 1)
  452. {
  453. aOuts = 2;
  454. forcedStereoOut = true;
  455. }
  456. }
  457. if (aIns > 0)
  458. {
  459. kData->audioIn.createNew(aIns);
  460. fAudioInBuffers = new float*[aIns];
  461. for (uint32_t i=0; i < aIns; i++)
  462. fAudioInBuffers[i] = nullptr;
  463. }
  464. if (aOuts > 0)
  465. {
  466. kData->audioOut.createNew(aOuts);
  467. fAudioOutBuffers = new float*[aOuts];
  468. needsCtrlIn = true;
  469. for (uint32_t i=0; i < aOuts; i++)
  470. fAudioOutBuffers[i] = nullptr;
  471. }
  472. if (mIns > 0)
  473. {
  474. fMidiIn.createNew(mIns);
  475. needsCtrlIn = (mIns == 1);
  476. }
  477. if (mOuts > 0)
  478. {
  479. fMidiOut.createNew(mOuts);
  480. needsCtrlOut = (mOuts == 1);
  481. }
  482. if (params > 0)
  483. {
  484. kData->param.createNew(params);
  485. }
  486. const uint portNameSize = kData->engine->maxPortNameSize();
  487. CarlaString portName;
  488. // Audio Ins
  489. for (j=0; j < aIns; j++)
  490. {
  491. portName.clear();
  492. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  493. {
  494. portName = fName;
  495. portName += ":";
  496. }
  497. if (aIns > 1)
  498. {
  499. portName += "input_";
  500. portName += CarlaString(j+1);
  501. }
  502. else
  503. portName += "input";
  504. portName.truncate(portNameSize);
  505. kData->audioIn.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, true);
  506. kData->audioIn.ports[j].rindex = j;
  507. if (forcedStereoIn)
  508. {
  509. portName += "_2";
  510. kData->audioIn.ports[1].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, true);
  511. kData->audioIn.ports[1].rindex = j;
  512. break;
  513. }
  514. }
  515. // Audio Outs
  516. for (j=0; j < aOuts; j++)
  517. {
  518. portName.clear();
  519. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  520. {
  521. portName = fName;
  522. portName += ":";
  523. }
  524. if (aOuts > 1)
  525. {
  526. portName += "output_";
  527. portName += CarlaString(j+1);
  528. }
  529. else
  530. portName += "output";
  531. portName.truncate(portNameSize);
  532. kData->audioOut.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false);
  533. kData->audioOut.ports[j].rindex = j;
  534. if (forcedStereoOut)
  535. {
  536. portName += "_2";
  537. kData->audioOut.ports[1].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false);
  538. kData->audioOut.ports[1].rindex = j;
  539. break;
  540. }
  541. }
  542. // MIDI Input (only if multiple)
  543. if (mIns > 1)
  544. {
  545. for (j=0; j < mIns; j++)
  546. {
  547. portName.clear();
  548. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  549. {
  550. portName = fName;
  551. portName += ":";
  552. }
  553. portName += "midi-in_";
  554. portName += CarlaString(j+1);
  555. portName.truncate(portNameSize);
  556. fMidiIn.ports[j] = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, true);
  557. fMidiIn.indexes[j] = j;
  558. }
  559. }
  560. // MIDI Output (only if multiple)
  561. if (mOuts > 1)
  562. {
  563. for (j=0; j < mOuts; j++)
  564. {
  565. portName.clear();
  566. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  567. {
  568. portName = fName;
  569. portName += ":";
  570. }
  571. portName += "midi-out_";
  572. portName += CarlaString(j+1);
  573. portName.truncate(portNameSize);
  574. fMidiOut.ports[j] = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, false);
  575. fMidiOut.indexes[j] = j;
  576. }
  577. }
  578. for (j=0; j < params; j++)
  579. {
  580. const ::Parameter* const paramInfo = fDescriptor->get_parameter_info(fHandle, j);
  581. kData->param.data[j].index = j;
  582. kData->param.data[j].rindex = j;
  583. kData->param.data[j].hints = 0x0;
  584. kData->param.data[j].midiChannel = 0;
  585. kData->param.data[j].midiCC = -1;
  586. float min, max, def, step, stepSmall, stepLarge;
  587. // min value
  588. min = paramInfo->ranges.min;
  589. // max value
  590. max = paramInfo->ranges.max;
  591. if (min > max)
  592. max = min;
  593. else if (max < min)
  594. min = max;
  595. if (max - min == 0.0f)
  596. {
  597. carla_stderr2("WARNING - Broken plugin parameter '%s': max - min == 0.0f", paramInfo->name);
  598. max = min + 0.1f;
  599. }
  600. // default value
  601. def = paramInfo->ranges.def;
  602. if (def < min)
  603. def = min;
  604. else if (def > max)
  605. def = max;
  606. if (paramInfo->hints & ::PARAMETER_USES_SAMPLE_RATE)
  607. {
  608. min *= sampleRate;
  609. max *= sampleRate;
  610. def *= sampleRate;
  611. kData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE;
  612. }
  613. if (paramInfo->hints & ::PARAMETER_IS_BOOLEAN)
  614. {
  615. step = max - min;
  616. stepSmall = step;
  617. stepLarge = step;
  618. kData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
  619. }
  620. else if (paramInfo->hints & ::PARAMETER_IS_INTEGER)
  621. {
  622. step = 1.0f;
  623. stepSmall = 1.0f;
  624. stepLarge = 10.0f;
  625. kData->param.data[j].hints |= PARAMETER_IS_INTEGER;
  626. }
  627. else
  628. {
  629. float range = max - min;
  630. step = range/100.0f;
  631. stepSmall = range/1000.0f;
  632. stepLarge = range/10.0f;
  633. }
  634. if (paramInfo->hints & ::PARAMETER_IS_OUTPUT)
  635. {
  636. kData->param.data[j].type = PARAMETER_OUTPUT;
  637. needsCtrlOut = true;
  638. }
  639. else
  640. {
  641. kData->param.data[j].type = PARAMETER_INPUT;
  642. needsCtrlIn = true;
  643. }
  644. // extra parameter hints
  645. if (paramInfo->hints & ::PARAMETER_IS_ENABLED)
  646. kData->param.data[j].hints |= PARAMETER_IS_ENABLED;
  647. if (paramInfo->hints & ::PARAMETER_IS_AUTOMABLE)
  648. kData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
  649. if (paramInfo->hints & ::PARAMETER_IS_LOGARITHMIC)
  650. kData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
  651. if (paramInfo->hints & ::PARAMETER_USES_SCALEPOINTS)
  652. kData->param.data[j].hints |= PARAMETER_USES_SCALEPOINTS;
  653. if (paramInfo->hints & ::PARAMETER_USES_CUSTOM_TEXT)
  654. kData->param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT;
  655. kData->param.ranges[j].min = min;
  656. kData->param.ranges[j].max = max;
  657. kData->param.ranges[j].def = def;
  658. kData->param.ranges[j].step = step;
  659. kData->param.ranges[j].stepSmall = stepSmall;
  660. kData->param.ranges[j].stepLarge = stepLarge;
  661. }
  662. if (needsCtrlIn)
  663. {
  664. portName.clear();
  665. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  666. {
  667. portName = fName;
  668. portName += ":";
  669. }
  670. portName += "event-in";
  671. portName.truncate(portNameSize);
  672. kData->event.portIn = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, true);
  673. }
  674. if (needsCtrlOut)
  675. {
  676. portName.clear();
  677. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  678. {
  679. portName = fName;
  680. portName += ":";
  681. }
  682. portName += "event-out";
  683. portName.truncate(portNameSize);
  684. kData->event.portOut = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, false);
  685. }
  686. // plugin hints
  687. fHints = 0x0;
  688. if (aOuts > 0 && (aIns == aOuts || aIns == 1))
  689. fHints |= PLUGIN_CAN_DRYWET;
  690. if (aOuts > 0)
  691. fHints |= PLUGIN_CAN_VOLUME;
  692. if (aOuts >= 2 && aOuts % 2 == 0)
  693. fHints |= PLUGIN_CAN_BALANCE;
  694. // native plugin hints
  695. if (fDescriptor->hints & ::PLUGIN_IS_RTSAFE)
  696. fHints |= PLUGIN_IS_RTSAFE;
  697. if (fDescriptor->hints & ::PLUGIN_IS_SYNTH)
  698. fHints |= PLUGIN_IS_SYNTH;
  699. if (fDescriptor->hints & ::PLUGIN_HAS_GUI)
  700. fHints |= PLUGIN_HAS_GUI;
  701. if (fDescriptor->hints & ::PLUGIN_USES_SINGLE_THREAD)
  702. fHints |= PLUGIN_HAS_SINGLE_THREAD;
  703. // extra plugin hints
  704. kData->extraHints = 0x0;
  705. if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0) && mIns <= 1 && mOuts <= 1)
  706. kData->extraHints |= PLUGIN_HINT_CAN_RUN_RACK;
  707. // plugin options
  708. fOptions = 0x0;
  709. if (fDescriptor->name != nullptr)
  710. {
  711. if (std::strcmp(fDescriptor->name, "ZynAddSubFX") == 0)
  712. {
  713. fOptions |= PLUGIN_OPTION_FIXED_BUFFER;
  714. }
  715. }
  716. fOptions |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  717. if (forcedStereoIn || forcedStereoOut)
  718. fOptions |= PLUGIN_OPTION_FORCE_STEREO;
  719. if (mIns > 0)
  720. {
  721. fOptions |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  722. fOptions |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  723. fOptions |= PLUGIN_OPTION_SEND_PITCHBEND;
  724. fOptions |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  725. }
  726. bufferSizeChanged(kData->engine->getBufferSize());
  727. reloadPrograms(true);
  728. carla_debug("NativePlugin::reload() - end");
  729. }
  730. void reloadPrograms(const bool init)
  731. {
  732. carla_debug("NativePlugin::reloadPrograms(%s)", bool2str(init));
  733. uint32_t i, oldCount = kData->midiprog.count;
  734. // Delete old programs
  735. kData->midiprog.clear();
  736. // Query new programs
  737. uint32_t count = 0;
  738. if (fDescriptor->get_midi_program_count != nullptr && fDescriptor->get_midi_program_info != nullptr)
  739. count = fDescriptor->get_midi_program_count(fHandle);
  740. if (count > 0)
  741. kData->midiprog.createNew(count);
  742. // Update data
  743. for (i=0; i < kData->midiprog.count; i++)
  744. {
  745. const ::MidiProgram* const mpDesc = fDescriptor->get_midi_program_info(fHandle, i);
  746. CARLA_ASSERT(mpDesc != nullptr);
  747. CARLA_ASSERT(mpDesc->name != nullptr);
  748. kData->midiprog.data[i].bank = mpDesc->bank;
  749. kData->midiprog.data[i].program = mpDesc->program;
  750. kData->midiprog.data[i].name = carla_strdup(mpDesc->name);
  751. }
  752. #ifndef BUILD_BRIDGE
  753. // Update OSC Names
  754. if (kData->engine->isOscControlRegistered())
  755. {
  756. kData->engine->osc_send_control_set_midi_program_count(fId, kData->midiprog.count);
  757. for (i=0; i < kData->midiprog.count; i++)
  758. kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name);
  759. }
  760. #endif
  761. if (init)
  762. {
  763. if (kData->midiprog.count > 0)
  764. setMidiProgram(0, false, false, false);
  765. }
  766. else
  767. {
  768. kData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr);
  769. // Check if current program is invalid
  770. bool programChanged = false;
  771. if (kData->midiprog.count == oldCount+1)
  772. {
  773. // one midi program added, probably created by user
  774. kData->midiprog.current = oldCount;
  775. programChanged = true;
  776. }
  777. else if (kData->midiprog.current >= static_cast<int32_t>(kData->midiprog.count))
  778. {
  779. // current midi program > count
  780. kData->midiprog.current = 0;
  781. programChanged = true;
  782. }
  783. else if (kData->midiprog.current < 0 && kData->midiprog.count > 0)
  784. {
  785. // programs exist now, but not before
  786. kData->midiprog.current = 0;
  787. programChanged = true;
  788. }
  789. else if (kData->midiprog.current >= 0 && kData->midiprog.count == 0)
  790. {
  791. // programs existed before, but not anymore
  792. kData->midiprog.current = -1;
  793. programChanged = true;
  794. }
  795. if (programChanged)
  796. setMidiProgram(kData->midiprog.current, true, true, true);
  797. }
  798. }
  799. // -------------------------------------------------------------------
  800. // Plugin processing
  801. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames)
  802. {
  803. uint32_t i, k;
  804. // --------------------------------------------------------------------------------------------------------
  805. // Check if active
  806. if (! kData->active)
  807. {
  808. // disable any output sound
  809. for (i=0; i < kData->audioOut.count; i++)
  810. carla_zeroFloat(outBuffer[i], frames);
  811. if (kData->activeBefore)
  812. {
  813. if (fDescriptor->deactivate != nullptr)
  814. {
  815. fDescriptor->deactivate(fHandle);
  816. if (fHandle2 != nullptr)
  817. fDescriptor->deactivate(fHandle2);
  818. }
  819. }
  820. kData->activeBefore = kData->active;
  821. return;
  822. }
  823. fMidiEventCount = 0;
  824. carla_zeroMem(fMidiEvents, sizeof(::MidiEvent)*MAX_MIDI_EVENTS*2);
  825. // --------------------------------------------------------------------------------------------------------
  826. // Check if not active before
  827. if (! kData->activeBefore)
  828. {
  829. if (kData->event.portIn != nullptr)
  830. {
  831. for (k=0, i=MAX_MIDI_CHANNELS; k < MAX_MIDI_CHANNELS; k++)
  832. {
  833. fMidiEvents[k].data[0] = MIDI_STATUS_CONTROL_CHANGE + k;
  834. fMidiEvents[k].data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
  835. fMidiEvents[k+i].data[0] = MIDI_STATUS_CONTROL_CHANGE + k;
  836. fMidiEvents[k+i].data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
  837. }
  838. fMidiEventCount = MAX_MIDI_CHANNELS*2;
  839. }
  840. if (fDescriptor->activate != nullptr)
  841. {
  842. fDescriptor->activate(fHandle);
  843. if (fHandle2 != nullptr)
  844. fDescriptor->activate(fHandle2);
  845. }
  846. }
  847. CARLA_PROCESS_CONTINUE_CHECK;
  848. // --------------------------------------------------------------------------------------------------------
  849. // Set TimeInfo
  850. const EngineTimeInfo& timeInfo = kData->engine->getTimeInfo();
  851. fTimeInfo.playing = timeInfo.playing;
  852. fTimeInfo.frame = timeInfo.frame;
  853. fTimeInfo.time = timeInfo.time;
  854. if (timeInfo.valid & EngineTimeInfo::ValidBBT)
  855. {
  856. fTimeInfo.bbt.valid = true;
  857. fTimeInfo.bbt.bar = timeInfo.bbt.bar;
  858. fTimeInfo.bbt.beat = timeInfo.bbt.beat;
  859. fTimeInfo.bbt.tick = timeInfo.bbt.tick;
  860. fTimeInfo.bbt.barStartTick = timeInfo.bbt.barStartTick;
  861. fTimeInfo.bbt.beatsPerBar = timeInfo.bbt.beatsPerBar;
  862. fTimeInfo.bbt.beatType = timeInfo.bbt.beatType;
  863. fTimeInfo.bbt.ticksPerBeat = timeInfo.bbt.ticksPerBeat;
  864. fTimeInfo.bbt.beatsPerMinute = timeInfo.bbt.beatsPerMinute;
  865. }
  866. else
  867. fTimeInfo.bbt.valid = false;
  868. CARLA_PROCESS_CONTINUE_CHECK;
  869. // --------------------------------------------------------------------------------------------------------
  870. // Event Input and Processing
  871. if (kData->event.portIn != nullptr && kData->activeBefore)
  872. {
  873. // ----------------------------------------------------------------------------------------------------
  874. // MIDI Input (External)
  875. if (kData->extNotes.mutex.tryLock())
  876. {
  877. while (fMidiEventCount < MAX_MIDI_EVENTS*2 && ! kData->extNotes.data.isEmpty())
  878. {
  879. const ExternalMidiNote& note = kData->extNotes.data.getFirst(true);
  880. CARLA_ASSERT(note.channel >= 0);
  881. fMidiEvents[fMidiEventCount].port = 0;
  882. fMidiEvents[fMidiEventCount].time = 0;
  883. fMidiEvents[fMidiEventCount].data[0] = (note.velo > 0) ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF;
  884. fMidiEvents[fMidiEventCount].data[0] += note.channel;
  885. fMidiEvents[fMidiEventCount].data[1] = note.note;
  886. fMidiEvents[fMidiEventCount].data[2] = note.velo;
  887. fMidiEventCount += 1;
  888. }
  889. kData->extNotes.mutex.unlock();
  890. } // End of MIDI Input (External)
  891. // ----------------------------------------------------------------------------------------------------
  892. // Event Input (System)
  893. bool allNotesOffSent = false;
  894. bool sampleAccurate = (fOptions & PLUGIN_OPTION_FIXED_BUFFER) == 0;
  895. uint32_t time, nEvents = kData->event.portIn->getEventCount();
  896. uint32_t startTime = 0;
  897. uint32_t timeOffset = 0;
  898. uint32_t nextBankId = 0;
  899. if (kData->midiprog.current >= 0 && kData->midiprog.count > 0)
  900. nextBankId = kData->midiprog.data[kData->midiprog.current].bank;
  901. for (i=0; i < nEvents; i++)
  902. {
  903. const EngineEvent& event = kData->event.portIn->getEvent(i);
  904. time = event.time;
  905. if (time >= frames)
  906. continue;
  907. CARLA_ASSERT_INT2(time >= timeOffset, time, timeOffset);
  908. if (time > timeOffset && sampleAccurate)
  909. {
  910. if (processSingle(inBuffer, outBuffer, time - timeOffset, timeOffset))
  911. {
  912. if (fMidiEventCount > 0)
  913. {
  914. //carla_zeroMem(fMidiEvents, sizeof(::MidiEvent)*fMidiEventCount);
  915. fMidiEventCount = 0;
  916. }
  917. nextBankId = 0;
  918. timeOffset = time;
  919. }
  920. else
  921. startTime += timeOffset;
  922. }
  923. // Control change
  924. switch (event.type)
  925. {
  926. case kEngineEventTypeNull:
  927. break;
  928. case kEngineEventTypeControl:
  929. {
  930. const EngineControlEvent& ctrlEvent = event.ctrl;
  931. switch (ctrlEvent.type)
  932. {
  933. case kEngineControlEventTypeNull:
  934. break;
  935. case kEngineControlEventTypeParameter:
  936. {
  937. // Control backend stuff
  938. if (event.channel == kData->ctrlChannel)
  939. {
  940. double value;
  941. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (fHints & PLUGIN_CAN_DRYWET) > 0)
  942. {
  943. value = ctrlEvent.value;
  944. setDryWet(value, false, false);
  945. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
  946. continue;
  947. }
  948. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (fHints & PLUGIN_CAN_VOLUME) > 0)
  949. {
  950. value = ctrlEvent.value*127/100;
  951. setVolume(value, false, false);
  952. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
  953. continue;
  954. }
  955. if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (fHints & PLUGIN_CAN_BALANCE) > 0)
  956. {
  957. double left, right;
  958. value = ctrlEvent.value/0.5 - 1.0;
  959. if (value < 0.0)
  960. {
  961. left = -1.0;
  962. right = (value*2)+1.0;
  963. }
  964. else if (value > 0.0)
  965. {
  966. left = (value*2)-1.0;
  967. right = 1.0;
  968. }
  969. else
  970. {
  971. left = -1.0;
  972. right = 1.0;
  973. }
  974. setBalanceLeft(left, false, false);
  975. setBalanceRight(right, false, false);
  976. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  977. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  978. continue;
  979. }
  980. }
  981. // Control plugin parameters
  982. for (k=0; k < kData->param.count; k++)
  983. {
  984. if (kData->param.data[k].midiChannel != event.channel)
  985. continue;
  986. if (kData->param.data[k].midiCC != ctrlEvent.param)
  987. continue;
  988. if (kData->param.data[k].type != PARAMETER_INPUT)
  989. continue;
  990. if ((kData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
  991. continue;
  992. double value;
  993. if (kData->param.data[k].hints & PARAMETER_IS_BOOLEAN)
  994. {
  995. value = (ctrlEvent.value < 0.5f) ? kData->param.ranges[k].min : kData->param.ranges[k].max;
  996. }
  997. else
  998. {
  999. value = kData->param.ranges[i].unnormalizeValue(ctrlEvent.value);
  1000. if (kData->param.data[k].hints & PARAMETER_IS_INTEGER)
  1001. value = std::rint(value);
  1002. }
  1003. setParameterValue(k, value, false, false, false);
  1004. postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value);
  1005. }
  1006. break;
  1007. }
  1008. case kEngineControlEventTypeMidiBank:
  1009. if (event.channel == kData->ctrlChannel)
  1010. nextBankId = ctrlEvent.param;
  1011. break;
  1012. case kEngineControlEventTypeMidiProgram:
  1013. if (event.channel == kData->ctrlChannel)
  1014. {
  1015. const uint32_t nextProgramId = ctrlEvent.param;
  1016. for (k=0; k < kData->midiprog.count; k++)
  1017. {
  1018. if (kData->midiprog.data[k].bank == nextBankId && kData->midiprog.data[k].program == nextProgramId)
  1019. {
  1020. setMidiProgram(k, false, false, false);
  1021. postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0);
  1022. break;
  1023. }
  1024. }
  1025. }
  1026. break;
  1027. case kEngineControlEventTypeAllSoundOff:
  1028. if (event.channel == kData->ctrlChannel)
  1029. {
  1030. if (! allNotesOffSent)
  1031. sendMidiAllNotesOff();
  1032. if (fDescriptor->deactivate != nullptr)
  1033. {
  1034. fDescriptor->deactivate(fHandle);
  1035. if (fHandle2 != nullptr)
  1036. fDescriptor->deactivate(fHandle2);
  1037. }
  1038. if (fDescriptor->activate != nullptr)
  1039. {
  1040. fDescriptor->activate(fHandle);
  1041. if (fHandle2 != nullptr)
  1042. fDescriptor->activate(fHandle2);
  1043. }
  1044. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 0.0);
  1045. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 1.0);
  1046. allNotesOffSent = true;
  1047. }
  1048. if (fMidiEventCount >= MAX_MIDI_EVENTS*2)
  1049. continue;
  1050. fMidiEvents[fMidiEventCount].port = 0;
  1051. fMidiEvents[fMidiEventCount].time = sampleAccurate ? startTime : time;
  1052. fMidiEvents[fMidiEventCount].data[0] = MIDI_STATUS_CONTROL_CHANGE + event.channel;
  1053. fMidiEvents[fMidiEventCount].data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
  1054. fMidiEvents[fMidiEventCount].data[2] = 0;
  1055. fMidiEventCount += 1;
  1056. break;
  1057. case kEngineControlEventTypeAllNotesOff:
  1058. if (event.channel == kData->ctrlChannel)
  1059. {
  1060. if (! allNotesOffSent)
  1061. sendMidiAllNotesOff();
  1062. allNotesOffSent = true;
  1063. }
  1064. if (fMidiEventCount >= MAX_MIDI_EVENTS*2)
  1065. continue;
  1066. fMidiEvents[fMidiEventCount].port = 0;
  1067. fMidiEvents[fMidiEventCount].time = sampleAccurate ? startTime : time;
  1068. fMidiEvents[fMidiEventCount].data[0] = MIDI_STATUS_CONTROL_CHANGE + event.channel;
  1069. fMidiEvents[fMidiEventCount].data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
  1070. fMidiEvents[fMidiEventCount].data[2] = 0;
  1071. fMidiEventCount += 1;
  1072. break;
  1073. }
  1074. break;
  1075. }
  1076. case kEngineEventTypeMidi:
  1077. {
  1078. if (fMidiEventCount >= MAX_MIDI_EVENTS*2)
  1079. continue;
  1080. const EngineMidiEvent& midiEvent = event.midi;
  1081. uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent.data);
  1082. uint8_t channel = event.channel;
  1083. if (MIDI_IS_STATUS_AFTERTOUCH(status) && (fOptions & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
  1084. continue;
  1085. if (MIDI_IS_STATUS_CONTROL_CHANGE(status) && (fOptions & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
  1086. continue;
  1087. if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) && (fOptions & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
  1088. continue;
  1089. if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) && (fOptions & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
  1090. continue;
  1091. // Fix bad note-off
  1092. if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0)
  1093. status -= 0x10;
  1094. fMidiEvents[fMidiEventCount].port = 0;
  1095. fMidiEvents[fMidiEventCount].time = sampleAccurate ? startTime : time;
  1096. fMidiEvents[fMidiEventCount].data[0] = status + channel;
  1097. fMidiEvents[fMidiEventCount].data[1] = midiEvent.data[1];
  1098. fMidiEvents[fMidiEventCount].data[2] = midiEvent.data[2];
  1099. fMidiEventCount += 1;
  1100. if (status == MIDI_STATUS_NOTE_ON)
  1101. postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]);
  1102. else if (status == MIDI_STATUS_NOTE_OFF)
  1103. postponeRtEvent(kPluginPostRtEventNoteOff, channel, midiEvent.data[1], 0.0);
  1104. break;
  1105. }
  1106. }
  1107. }
  1108. kData->postRtEvents.trySplice();
  1109. if (frames > timeOffset)
  1110. processSingle(inBuffer, outBuffer, frames - timeOffset, timeOffset);
  1111. } // End of Event Input and Processing
  1112. // --------------------------------------------------------------------------------------------------------
  1113. // Plugin processing (no events)
  1114. else
  1115. {
  1116. processSingle(inBuffer, outBuffer, frames, 0);
  1117. } // End of Plugin processing (no events)
  1118. CARLA_PROCESS_CONTINUE_CHECK;
  1119. // --------------------------------------------------------------------------------------------------------
  1120. // Control and MIDI Output
  1121. if (fMidiOut.count > 0 || kData->event.portOut != nullptr)
  1122. {
  1123. float value, curValue;
  1124. for (k=0; k < kData->param.count; k++)
  1125. {
  1126. if (kData->param.data[k].type != PARAMETER_OUTPUT)
  1127. continue;
  1128. curValue = fDescriptor->get_parameter_value(fHandle, k);
  1129. kData->param.ranges[k].fixValue(curValue);
  1130. if (kData->param.data[k].midiCC > 0)
  1131. {
  1132. value = kData->param.ranges[k].normalizeValue(curValue);
  1133. kData->event.portOut->writeControlEvent(0, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value);
  1134. }
  1135. }
  1136. // reverse lookup MIDI events
  1137. for (k = (MAX_MIDI_EVENTS*2)-1; k >= fMidiEventCount; k--)
  1138. {
  1139. if (fMidiEvents[k].data[0] == 0)
  1140. break;
  1141. const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(fMidiEvents[k].data);
  1142. const uint8_t port = fMidiEvents[k].port;
  1143. if (kData->event.portOut != nullptr)
  1144. kData->event.portOut->writeMidiEvent(fMidiEvents[k].time, channel, port, fMidiEvents[k].data, 3);
  1145. else if (port < fMidiOut.count)
  1146. fMidiOut.ports[port]->writeMidiEvent(fMidiEvents[k].time, channel, port, fMidiEvents[k].data, 3);
  1147. }
  1148. } // End of Control and MIDI Output
  1149. // --------------------------------------------------------------------------------------------------------
  1150. kData->activeBefore = kData->active;
  1151. }
  1152. bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset)
  1153. {
  1154. uint32_t i, k;
  1155. // --------------------------------------------------------------------------------------------------------
  1156. // Try lock, silence otherwise
  1157. if (kData->engine->isOffline())
  1158. {
  1159. kData->mutex.lock();
  1160. }
  1161. else if (! kData->mutex.tryLock())
  1162. {
  1163. for (i=0; i < kData->audioOut.count; i++)
  1164. {
  1165. for (k=0; k < frames; k++)
  1166. outBuffer[i][k+timeOffset] = 0.0f;
  1167. }
  1168. return false;
  1169. }
  1170. for (i=0; i < kData->audioIn.count; i++)
  1171. carla_copyFloat(fAudioInBuffers[i], inBuffer[i]+timeOffset, frames);
  1172. for (i=0; i < kData->audioOut.count; i++)
  1173. carla_zeroFloat(fAudioOutBuffers[i], frames);
  1174. fIsProcessing = true;
  1175. if (fHandle2 == nullptr)
  1176. {
  1177. fDescriptor->process(fHandle, fAudioInBuffers, fAudioOutBuffers, frames, fMidiEventCount, fMidiEvents);
  1178. }
  1179. else
  1180. {
  1181. fDescriptor->process(fHandle,
  1182. (kData->audioIn.count > 0) ? &fAudioInBuffers[0] : nullptr,
  1183. (kData->audioOut.count > 0) ? &fAudioOutBuffers[0] : nullptr,
  1184. frames, fMidiEventCount, fMidiEvents);
  1185. fDescriptor->process(fHandle2,
  1186. (kData->audioIn.count > 0) ? &fAudioInBuffers[1] : nullptr,
  1187. (kData->audioOut.count > 0) ? &fAudioOutBuffers[1] : nullptr,
  1188. frames, fMidiEventCount, fMidiEvents);
  1189. }
  1190. fIsProcessing = false;
  1191. fTimeInfo.frame += frames;
  1192. // --------------------------------------------------------------------------------------------------------
  1193. // Post-processing (dry/wet, volume and balance)
  1194. {
  1195. const bool doDryWet = (fHints & PLUGIN_CAN_DRYWET) > 0 && kData->postProc.dryWet != 1.0f;
  1196. const bool doBalance = (fHints & PLUGIN_CAN_BALANCE) > 0 && (kData->postProc.balanceLeft != -1.0f || kData->postProc.balanceRight != 1.0f);
  1197. float bufValue, oldBufLeft[doBalance ? frames : 1];
  1198. for (i=0; i < kData->audioOut.count; i++)
  1199. {
  1200. // Dry/Wet
  1201. if (doDryWet)
  1202. {
  1203. for (k=0; k < frames; k++)
  1204. {
  1205. bufValue = fAudioInBuffers[(kData->audioIn.count == 1) ? 0 : i][k];
  1206. fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * kData->postProc.dryWet) + (bufValue * (1.0f - kData->postProc.dryWet));
  1207. }
  1208. }
  1209. // Balance
  1210. if (doBalance)
  1211. {
  1212. if (i % 2 == 0)
  1213. carla_copyFloat(oldBufLeft, fAudioOutBuffers[i], frames);
  1214. float balRangeL = (kData->postProc.balanceLeft + 1.0f)/2.0f;
  1215. float balRangeR = (kData->postProc.balanceRight + 1.0f)/2.0f;
  1216. for (k=0; k < frames; k++)
  1217. {
  1218. if (i % 2 == 0)
  1219. {
  1220. // left
  1221. fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  1222. fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR);
  1223. }
  1224. else
  1225. {
  1226. // right
  1227. fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR;
  1228. fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL;
  1229. }
  1230. }
  1231. }
  1232. // Volume (and buffer copy)
  1233. {
  1234. for (k=0; k < frames; k++)
  1235. outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k] * kData->postProc.volume;
  1236. }
  1237. }
  1238. } // End of Post-processing
  1239. // --------------------------------------------------------------------------------------------------------
  1240. kData->mutex.unlock();
  1241. return true;
  1242. }
  1243. void bufferSizeChanged(const uint32_t newBufferSize)
  1244. {
  1245. for (uint32_t i=0; i < kData->audioIn.count; i++)
  1246. {
  1247. if (fAudioInBuffers[i] != nullptr)
  1248. delete[] fAudioInBuffers[i];
  1249. fAudioInBuffers[i] = new float[newBufferSize];
  1250. }
  1251. for (uint32_t i=0; i < kData->audioOut.count; i++)
  1252. {
  1253. if (fAudioOutBuffers[i] != nullptr)
  1254. delete[] fAudioOutBuffers[i];
  1255. fAudioOutBuffers[i] = new float[newBufferSize];
  1256. }
  1257. }
  1258. // -------------------------------------------------------------------
  1259. // Post-poned events
  1260. void uiParameterChange(const uint32_t index, const float value)
  1261. {
  1262. CARLA_ASSERT(fDescriptor != nullptr);
  1263. CARLA_ASSERT(fHandle != nullptr);
  1264. CARLA_ASSERT(index < kData->param.count);
  1265. if (! fIsUiVisible)
  1266. return;
  1267. if (fDescriptor == nullptr || fHandle == nullptr)
  1268. return;
  1269. if (index >= kData->param.count)
  1270. return;
  1271. fDescriptor->ui_set_parameter_value(fHandle, index, value);
  1272. }
  1273. void uiMidiProgramChange(const uint32_t index)
  1274. {
  1275. CARLA_ASSERT(fDescriptor != nullptr);
  1276. CARLA_ASSERT(fHandle != nullptr);
  1277. CARLA_ASSERT(index < kData->midiprog.count);
  1278. if (! fIsUiVisible)
  1279. return;
  1280. if (fDescriptor == nullptr || fHandle == nullptr)
  1281. return;
  1282. if (index >= kData->midiprog.count)
  1283. return;
  1284. fDescriptor->ui_set_parameter_value(fHandle, kData->midiprog.data[index].bank, kData->midiprog.data[index].program);
  1285. }
  1286. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo)
  1287. {
  1288. CARLA_ASSERT(fDescriptor != nullptr);
  1289. CARLA_ASSERT(fHandle != nullptr);
  1290. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  1291. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  1292. CARLA_ASSERT(velo > 0 && velo < MAX_MIDI_VALUE);
  1293. if (! fIsUiVisible)
  1294. return;
  1295. if (fDescriptor == nullptr || fHandle == nullptr)
  1296. return;
  1297. if (channel >= MAX_MIDI_CHANNELS)
  1298. return;
  1299. if (note >= MAX_MIDI_NOTE)
  1300. return;
  1301. if (velo >= MAX_MIDI_VALUE)
  1302. return;
  1303. // TODO
  1304. }
  1305. void uiNoteOff(const uint8_t channel, const uint8_t note)
  1306. {
  1307. CARLA_ASSERT(fDescriptor != nullptr);
  1308. CARLA_ASSERT(fHandle != nullptr);
  1309. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  1310. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  1311. if (! fIsUiVisible)
  1312. return;
  1313. if (fDescriptor == nullptr || fHandle == nullptr)
  1314. return;
  1315. if (channel >= MAX_MIDI_CHANNELS)
  1316. return;
  1317. if (note >= MAX_MIDI_NOTE)
  1318. return;
  1319. // TODO
  1320. }
  1321. // -------------------------------------------------------------------
  1322. // Cleanup
  1323. void initBuffers()
  1324. {
  1325. fMidiIn.initBuffers(kData->engine);
  1326. fMidiOut.initBuffers(kData->engine);
  1327. CarlaPlugin::initBuffers();
  1328. }
  1329. void deleteBuffers()
  1330. {
  1331. carla_debug("NativePlugin::deleteBuffers() - start");
  1332. if (fAudioInBuffers != nullptr)
  1333. {
  1334. for (uint32_t i=0; i < kData->audioIn.count; i++)
  1335. {
  1336. if (fAudioInBuffers[i] != nullptr)
  1337. {
  1338. delete[] fAudioInBuffers[i];
  1339. fAudioInBuffers[i] = nullptr;
  1340. }
  1341. }
  1342. delete[] fAudioInBuffers;
  1343. fAudioInBuffers = nullptr;
  1344. }
  1345. if (fAudioOutBuffers != nullptr)
  1346. {
  1347. for (uint32_t i=0; i < kData->audioOut.count; i++)
  1348. {
  1349. if (fAudioOutBuffers[i] != nullptr)
  1350. {
  1351. delete[] fAudioOutBuffers[i];
  1352. fAudioOutBuffers[i] = nullptr;
  1353. }
  1354. }
  1355. delete[] fAudioOutBuffers;
  1356. fAudioOutBuffers = nullptr;
  1357. }
  1358. fMidiIn.clear();
  1359. fMidiOut.clear();
  1360. CarlaPlugin::deleteBuffers();
  1361. carla_debug("NativePlugin::deleteBuffers() - end");
  1362. }
  1363. // -------------------------------------------------------------------
  1364. protected:
  1365. uint32_t handleGetBufferSize()
  1366. {
  1367. return kData->engine->getBufferSize();
  1368. }
  1369. double handleGetSampleRate()
  1370. {
  1371. return kData->engine->getSampleRate();
  1372. }
  1373. const ::TimeInfo* handleGetTimeInfo()
  1374. {
  1375. CARLA_ASSERT(fIsProcessing);
  1376. return &fTimeInfo;
  1377. }
  1378. bool handleWriteMidiEvent(const ::MidiEvent* const event)
  1379. {
  1380. CARLA_ASSERT(fEnabled);
  1381. CARLA_ASSERT(fMidiOut.count > 0 || kData->event.portOut != nullptr);
  1382. CARLA_ASSERT(event != nullptr);
  1383. CARLA_ASSERT(fIsProcessing);
  1384. if (! fEnabled)
  1385. return false;
  1386. if (fMidiOut.count == 0)
  1387. return false;
  1388. if (event == nullptr)
  1389. return false;
  1390. if (! fIsProcessing)
  1391. {
  1392. carla_stderr2("NativePlugin::handleWriteMidiEvent(%p) - received MIDI out event outside audio thread, ignoring", event);
  1393. return false;
  1394. }
  1395. if (fMidiEventCount >= MAX_MIDI_EVENTS*2)
  1396. return false;
  1397. // reverse-find first free event, and put it there
  1398. for (uint32_t i=(MAX_MIDI_EVENTS*2)-1; i >= fMidiEventCount; i--)
  1399. {
  1400. if (fMidiEvents[i].data[0] == 0)
  1401. {
  1402. std::memcpy(&fMidiEvents[i], event, sizeof(::MidiEvent));
  1403. break;
  1404. }
  1405. }
  1406. return true;
  1407. }
  1408. void handleUiParameterChanged(const uint32_t index, const float value)
  1409. {
  1410. setParameterValue(index, value, false, true, true);
  1411. }
  1412. void handleUiCustomDataChanged(const char* const key, const char* const value)
  1413. {
  1414. setCustomData(CUSTOM_DATA_STRING, key, value, false);
  1415. }
  1416. void handleUiClosed()
  1417. {
  1418. kData->engine->callback(CALLBACK_SHOW_GUI, fId, 0, 0, 0.0f, nullptr);
  1419. fIsUiVisible = false;
  1420. }
  1421. const char* handleUiOpenFile(const bool isDir, const char* const title, const char* const filter)
  1422. {
  1423. static CarlaString retStr;
  1424. retStr = QFileDialog::getOpenFileName(nullptr, title, "", filter).toUtf8().constData();
  1425. return retStr.isNotEmpty() ? (const char*)retStr : nullptr;
  1426. // TODO - isDir
  1427. }
  1428. const char* handleUiSaveFile(const bool isDir, const char* const title, const char* const filter)
  1429. {
  1430. static CarlaString retStr;
  1431. retStr = QFileDialog::getSaveFileName(nullptr, title, "", filter).toUtf8().constData();
  1432. return (const char*)retStr;
  1433. // TODO - isDir
  1434. }
  1435. public:
  1436. static size_t getPluginCount()
  1437. {
  1438. return sPluginDescriptors.count();
  1439. }
  1440. static const PluginDescriptor* getPluginDescriptor(const size_t index)
  1441. {
  1442. CARLA_ASSERT(index < sPluginDescriptors.count());
  1443. if (index < sPluginDescriptors.count())
  1444. return sPluginDescriptors.getAt(index);
  1445. return nullptr;
  1446. }
  1447. static void registerPlugin(const PluginDescriptor* desc)
  1448. {
  1449. sPluginDescriptors.append(desc);
  1450. }
  1451. // -------------------------------------------------------------------
  1452. bool init(const char* const name, const char* const label)
  1453. {
  1454. CARLA_ASSERT(kData->engine != nullptr);
  1455. CARLA_ASSERT(kData->client == nullptr);
  1456. CARLA_ASSERT(label);
  1457. // ---------------------------------------------------------------
  1458. // get descriptor that matches label
  1459. // FIXME - use itenerator when available
  1460. for (size_t i=0; i < sPluginDescriptors.count(); i++)
  1461. {
  1462. fDescriptor = sPluginDescriptors.getAt(i);
  1463. if (fDescriptor == nullptr)
  1464. break;
  1465. if (fDescriptor->label != nullptr && std::strcmp(fDescriptor->label, label) == 0)
  1466. break;
  1467. fDescriptor = nullptr;
  1468. }
  1469. if (fDescriptor == nullptr)
  1470. {
  1471. kData->engine->setLastError("Invalid internal plugin");
  1472. return false;
  1473. }
  1474. // ---------------------------------------------------------------
  1475. // get info
  1476. if (name != nullptr)
  1477. fName = kData->engine->getNewUniquePluginName(name);
  1478. else if (fDescriptor->name != nullptr)
  1479. fName = kData->engine->getNewUniquePluginName(fDescriptor->name);
  1480. else
  1481. fName = kData->engine->getNewUniquePluginName(fDescriptor->name);
  1482. // ---------------------------------------------------------------
  1483. // register client
  1484. kData->client = kData->engine->addClient(this);
  1485. if (kData->client == nullptr || ! kData->client->isOk())
  1486. {
  1487. kData->engine->setLastError("Failed to register plugin client");
  1488. return false;
  1489. }
  1490. // ---------------------------------------------------------------
  1491. // initialize plugin
  1492. fHandle = fDescriptor->instantiate(fDescriptor, &fHost);
  1493. if (fHandle == nullptr)
  1494. {
  1495. kData->engine->setLastError("Plugin failed to initialize");
  1496. return false;
  1497. }
  1498. return true;
  1499. }
  1500. class ScopedInitializer
  1501. {
  1502. public:
  1503. ScopedInitializer()
  1504. {
  1505. initDescriptors();
  1506. }
  1507. ~ScopedInitializer()
  1508. {
  1509. clearDescriptors();
  1510. }
  1511. };
  1512. private:
  1513. PluginHandle fHandle;
  1514. PluginHandle fHandle2;
  1515. HostDescriptor fHost;
  1516. const PluginDescriptor* fDescriptor;
  1517. bool fIsProcessing;
  1518. bool fIsUiVisible;
  1519. float** fAudioInBuffers;
  1520. float** fAudioOutBuffers;
  1521. uint32_t fMidiEventCount;
  1522. ::MidiEvent fMidiEvents[MAX_MIDI_EVENTS*2];
  1523. NativePluginMidiData fMidiIn;
  1524. NativePluginMidiData fMidiOut;
  1525. ::TimeInfo fTimeInfo;
  1526. static NonRtList<const PluginDescriptor*> sPluginDescriptors;
  1527. // -------------------------------------------------------------------
  1528. static void initDescriptors()
  1529. {
  1530. #ifndef BUILD_BRIDGE
  1531. carla_register_native_plugin_bypass();
  1532. carla_register_native_plugin_midiSequencer();
  1533. carla_register_native_plugin_midiSplit();
  1534. carla_register_native_plugin_midiThrough();
  1535. carla_register_native_plugin_midiTranspose();
  1536. carla_register_native_plugin_nekofilter();
  1537. carla_register_native_plugin_3BandEQ();
  1538. carla_register_native_plugin_3BandSplitter();
  1539. carla_register_native_plugin_PingPongPan();
  1540. carla_register_native_plugin_Notes();
  1541. # ifdef WANT_AUDIOFILE
  1542. carla_register_native_plugin_audiofile();
  1543. # endif
  1544. # ifdef WANT_ZYNADDSUBFX
  1545. carla_register_native_plugin_zynaddsubfx();
  1546. # endif
  1547. #endif
  1548. }
  1549. static void clearDescriptors()
  1550. {
  1551. sPluginDescriptors.clear();
  1552. }
  1553. // -------------------------------------------------------------------
  1554. #define handlePtr ((NativePlugin*)handle)
  1555. static uint32_t carla_host_get_buffer_size(HostHandle handle)
  1556. {
  1557. return handlePtr->handleGetBufferSize();
  1558. }
  1559. static double carla_host_get_sample_rate(HostHandle handle)
  1560. {
  1561. return handlePtr->handleGetSampleRate();
  1562. }
  1563. static const ::TimeInfo* carla_host_get_time_info(HostHandle handle)
  1564. {
  1565. return handlePtr->handleGetTimeInfo();
  1566. }
  1567. static bool carla_host_write_midi_event(HostHandle handle, const ::MidiEvent* event)
  1568. {
  1569. return handlePtr->handleWriteMidiEvent(event);
  1570. }
  1571. static void carla_host_ui_parameter_changed(HostHandle handle, uint32_t index, float value)
  1572. {
  1573. handlePtr->handleUiParameterChanged(index, value);
  1574. }
  1575. static void carla_host_ui_custom_data_changed(HostHandle handle, const char* key, const char* value)
  1576. {
  1577. handlePtr->handleUiCustomDataChanged(key, value);
  1578. }
  1579. static void carla_host_ui_closed(HostHandle handle)
  1580. {
  1581. handlePtr->handleUiClosed();
  1582. }
  1583. static const char* carla_host_ui_open_file(HostHandle handle, bool isDir, const char* title, const char* filter)
  1584. {
  1585. return handlePtr->handleUiOpenFile(isDir, title, filter);
  1586. }
  1587. static const char* carla_host_ui_save_file(HostHandle handle, bool isDir, const char* title, const char* filter)
  1588. {
  1589. return handlePtr->handleUiSaveFile(isDir, title, filter);
  1590. }
  1591. #undef handlePtr
  1592. };
  1593. NonRtList<const PluginDescriptor*> NativePlugin::sPluginDescriptors;
  1594. static const NativePlugin::ScopedInitializer _si;
  1595. CARLA_BACKEND_END_NAMESPACE
  1596. void carla_register_native_plugin(const PluginDescriptor* desc)
  1597. {
  1598. CARLA_BACKEND_USE_NAMESPACE
  1599. NativePlugin::registerPlugin(desc);
  1600. }
  1601. #else // WANT_NATIVE
  1602. # warning Building without Internal plugin support
  1603. #endif
  1604. CARLA_BACKEND_START_NAMESPACE
  1605. size_t CarlaPlugin::getNativePluginCount()
  1606. {
  1607. #ifdef WANT_NATIVE
  1608. return NativePlugin::getPluginCount();
  1609. #else
  1610. return 0;
  1611. #endif
  1612. }
  1613. const PluginDescriptor* CarlaPlugin::getNativePluginDescriptor(const size_t index)
  1614. {
  1615. #ifdef WANT_NATIVE
  1616. return NativePlugin::getPluginDescriptor(index);
  1617. #else
  1618. return nullptr;
  1619. // unused
  1620. (void)index;
  1621. #endif
  1622. }
  1623. // -----------------------------------------------------------------------
  1624. CarlaPlugin* CarlaPlugin::newNative(const Initializer& init)
  1625. {
  1626. carla_debug("CarlaPlugin::newNative(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label);
  1627. #ifdef WANT_NATIVE
  1628. NativePlugin* const plugin = new NativePlugin(init.engine, init.id);
  1629. if (! plugin->init(init.name, init.label))
  1630. {
  1631. delete plugin;
  1632. return nullptr;
  1633. }
  1634. plugin->reload();
  1635. if (init.engine->getProccessMode() == PROCESS_MODE_CONTINUOUS_RACK && ! CarlaPluginProtectedData::canRunInRack(plugin))
  1636. {
  1637. init.engine->setLastError("Carla's rack mode can only work with Mono or Stereo Internal plugins, sorry!");
  1638. delete plugin;
  1639. return nullptr;
  1640. }
  1641. return plugin;
  1642. #else
  1643. init.engine->setLastError("Internal plugins not available");
  1644. return nullptr;
  1645. #endif
  1646. }
  1647. CARLA_BACKEND_END_NAMESPACE