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.

2202 lines
72KB

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