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.

1605 lines
52KB

  1. /*
  2. * Carla Plugin Engine (Native)
  3. * Copyright (C) 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 doc/GPL.txt file.
  16. */
  17. #include "CarlaDefines.h"
  18. #ifdef BUILD_BRIDGE
  19. # error This file should not be compiled if building bridge
  20. #endif
  21. #ifdef CARLA_OS_WIN
  22. # error This file should not be compiled for Windows
  23. #endif
  24. #include "CarlaEngineInternal.hpp"
  25. #include "CarlaPipeUtils.hpp"
  26. #include "CarlaStateUtils.hpp"
  27. #include "CarlaNative.hpp"
  28. #include <QtCore/QTextStream>
  29. CARLA_BACKEND_START_NAMESPACE
  30. // -----------------------------------------------------------------------
  31. class CarlaEngineNativeUI : public CarlaPipeServer
  32. {
  33. public:
  34. enum UiState {
  35. UiNone = 0,
  36. UiHide,
  37. UiShow,
  38. UiCrashed
  39. };
  40. CarlaEngineNativeUI(CarlaEngine* const engine)
  41. : fEngine(engine),
  42. fUiState(UiNone)
  43. {
  44. carla_debug("CarlaEngineNativeUI::CarlaEngineNativeUI(%p)", engine);
  45. }
  46. ~CarlaEngineNativeUI() override
  47. {
  48. CARLA_ASSERT_INT(fUiState == UiNone, fUiState);
  49. carla_debug("CarlaEngineNativeUI::~CarlaEngineNativeUI()");
  50. }
  51. void setData(const char* const filename, const double sampleRate, const char* const uiTitle)
  52. {
  53. fFilename = filename;
  54. fSampleRate = CarlaString(sampleRate);
  55. fUiTitle = uiTitle;
  56. }
  57. UiState getAndResetUiState() noexcept
  58. {
  59. const UiState uiState(fUiState);
  60. fUiState = UiNone;
  61. return uiState;
  62. }
  63. void start()
  64. {
  65. CarlaPipeServer::start(fFilename, fSampleRate, fUiTitle);
  66. writeMsg("show\n", 5);
  67. }
  68. protected:
  69. void msgReceived(const char* const msg) override
  70. {
  71. if (std::strcmp(msg, "exiting") == 0)
  72. {
  73. waitChildClose();
  74. fUiState = UiHide;
  75. }
  76. else if (std::strcmp(msg, "set_engine_option") == 0)
  77. {
  78. int option, value;
  79. const char* valueStr;
  80. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(option),);
  81. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(value),);
  82. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(valueStr),);
  83. fEngine->setOption((EngineOption)option, value, valueStr);
  84. delete[] valueStr;
  85. }
  86. else if (std::strcmp(msg, "load_file") == 0)
  87. {
  88. const char* filename;
  89. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),);
  90. fEngine->loadFile(filename);
  91. delete[] filename;
  92. }
  93. else if (std::strcmp(msg, "load_project") == 0)
  94. {
  95. const char* filename;
  96. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),);
  97. fEngine->loadProject(filename);
  98. delete[] filename;
  99. }
  100. else if (std::strcmp(msg, "save_project") == 0)
  101. {
  102. const char* filename;
  103. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),);
  104. fEngine->saveProject(filename);
  105. delete[] filename;
  106. }
  107. else if (std::strcmp(msg, "patchbay_connect") == 0)
  108. {
  109. int portA, portB;
  110. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(portA),);
  111. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(portB),);
  112. fEngine->patchbayConnect(portA, portB);
  113. }
  114. else if (std::strcmp(msg, "patchbay_disconnect") == 0)
  115. {
  116. int connectionId;
  117. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(connectionId),);
  118. fEngine->patchbayDisconnect(connectionId);
  119. }
  120. else if (std::strcmp(msg, "patchbay_refresh") == 0)
  121. {
  122. fEngine->patchbayRefresh();
  123. }
  124. else if (std::strcmp(msg, "transport_play") == 0)
  125. {
  126. fEngine->transportPlay();
  127. }
  128. else if (std::strcmp(msg, "transport_pause") == 0)
  129. {
  130. fEngine->transportPause();
  131. }
  132. else if (std::strcmp(msg, "transport_relocate") == 0)
  133. {
  134. long frame;
  135. CARLA_SAFE_ASSERT_RETURN(readNextLineAsLong(frame),);
  136. fEngine->transportRelocate((uint64_t)frame);
  137. }
  138. else if (std::strcmp(msg, "add_plugin") == 0)
  139. {
  140. int btype, ptype;
  141. const char* filename = nullptr;
  142. const char* name;
  143. const char* label;
  144. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(btype),);
  145. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(ptype),);
  146. readNextLineAsString(filename); // can be null
  147. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(name),);
  148. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(label),);
  149. if (filename != nullptr && std::strcmp(filename, "(null)") == 0)
  150. {
  151. delete[] filename;
  152. filename = nullptr;
  153. }
  154. if (std::strcmp(name, "(null)") == 0)
  155. {
  156. delete[] name;
  157. name = nullptr;
  158. }
  159. fEngine->addPlugin((BinaryType)btype, (PluginType)ptype, filename, name, label);
  160. if (filename != nullptr)
  161. delete[] filename;
  162. if (name != nullptr)
  163. delete[] name;
  164. delete[] label;
  165. }
  166. else if (std::strcmp(msg, "remove_plugin") == 0)
  167. {
  168. int pluginId;
  169. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  170. fEngine->removePlugin(pluginId);
  171. }
  172. else if (std::strcmp(msg, "remove_all_plugins") == 0)
  173. {
  174. fEngine->removeAllPlugins();
  175. }
  176. else if (std::strcmp(msg, "rename_plugin") == 0)
  177. {
  178. int pluginId;
  179. const char* newName;
  180. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  181. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(newName),);
  182. /*const char* name =*/ fEngine->renamePlugin(pluginId, newName);
  183. delete[] newName;
  184. }
  185. else if (std::strcmp(msg, "clone_plugin") == 0)
  186. {
  187. int pluginId;
  188. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  189. fEngine->clonePlugin(pluginId);
  190. }
  191. else if (std::strcmp(msg, "replace_plugin") == 0)
  192. {
  193. int pluginId;
  194. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  195. fEngine->replacePlugin(pluginId);
  196. }
  197. else if (std::strcmp(msg, "switch_plugins") == 0)
  198. {
  199. int pluginIdA, pluginIdB;
  200. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginIdA),);
  201. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginIdB),);
  202. fEngine->switchPlugins(pluginIdA, pluginIdB);
  203. }
  204. else if (std::strcmp(msg, "load_plugin_state") == 0)
  205. {
  206. int pluginId;
  207. const char* filename;
  208. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  209. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),);
  210. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  211. plugin->loadStateFromFile(filename);
  212. delete[] filename;
  213. }
  214. else if (std::strcmp(msg, "save_plugin_state") == 0)
  215. {
  216. int pluginId;
  217. const char* filename;
  218. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  219. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),);
  220. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  221. plugin->saveStateToFile(filename);
  222. delete[] filename;
  223. }
  224. else if (std::strcmp(msg, "set_option") == 0)
  225. {
  226. int pluginId;
  227. int option;
  228. bool yesNo;
  229. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  230. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(option),);
  231. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo),);
  232. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  233. plugin->setOption(option, yesNo);
  234. }
  235. else if (std::strcmp(msg, "set_active") == 0)
  236. {
  237. int pluginId;
  238. bool onOff;
  239. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  240. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(onOff),);
  241. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  242. plugin->setActive(onOff, true, false);
  243. }
  244. else if (std::strcmp(msg, "set_drywet") == 0)
  245. {
  246. int pluginId;
  247. float value;
  248. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  249. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),);
  250. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  251. plugin->setDryWet(value, true, false);
  252. }
  253. else if (std::strcmp(msg, "set_volume") == 0)
  254. {
  255. int pluginId;
  256. float value;
  257. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  258. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),);
  259. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  260. plugin->setVolume(value, true, false);
  261. }
  262. else if (std::strcmp(msg, "set_balance_left") == 0)
  263. {
  264. int pluginId;
  265. float value;
  266. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  267. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),);
  268. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  269. plugin->setBalanceLeft(value, true, false);
  270. }
  271. else if (std::strcmp(msg, "set_balance_right") == 0)
  272. {
  273. int pluginId;
  274. float value;
  275. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  276. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),);
  277. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  278. plugin->setBalanceRight(value, true, false);
  279. }
  280. else if (std::strcmp(msg, "set_panning") == 0)
  281. {
  282. int pluginId;
  283. float value;
  284. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  285. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),);
  286. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  287. plugin->setPanning(value, true, false);
  288. }
  289. else if (std::strcmp(msg, "set_ctrl_channel") == 0)
  290. {
  291. int pluginId;
  292. int channel;
  293. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  294. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(channel),);
  295. CARLA_SAFE_ASSERT_RETURN(channel >= -1 && channel < MAX_MIDI_CHANNELS,);
  296. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  297. plugin->setCtrlChannel(int8_t(channel), true, false);
  298. }
  299. else if (std::strcmp(msg, "set_parameter_value") == 0)
  300. {
  301. int pluginId;
  302. int parameterId;
  303. float value;
  304. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  305. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(parameterId),);
  306. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),);
  307. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  308. plugin->setParameterValue(parameterId, value, true, true, false);
  309. }
  310. else if (std::strcmp(msg, "set_parameter_midi_channel") == 0)
  311. {
  312. int pluginId;
  313. int parameterId;
  314. int channel;
  315. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  316. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(parameterId),);
  317. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(channel),);
  318. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS,);
  319. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  320. plugin->setParameterMidiChannel(parameterId, uint8_t(channel), true, false);
  321. }
  322. else if (std::strcmp(msg, "set_parameter_midi_cc") == 0)
  323. {
  324. int pluginId;
  325. int parameterId;
  326. int cc;
  327. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  328. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(parameterId),);
  329. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(cc),);
  330. CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < 0x5F,);
  331. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  332. plugin->setParameterMidiCC(parameterId, int16_t(cc), true, false);
  333. }
  334. else if (std::strcmp(msg, "set_program") == 0)
  335. {
  336. int pluginId;
  337. int index;
  338. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  339. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index),);
  340. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  341. plugin->setProgram(index, true, true, false);
  342. }
  343. else if (std::strcmp(msg, "set_midi_program") == 0)
  344. {
  345. int pluginId;
  346. int index;
  347. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  348. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index),);
  349. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  350. plugin->setMidiProgram(index, true, true, false);
  351. }
  352. else if (std::strcmp(msg, "set_custom_data") == 0)
  353. {
  354. int pluginId;
  355. const char* type;
  356. const char* key;
  357. const char* value;
  358. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  359. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(type),);
  360. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(key),);
  361. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(value),);
  362. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  363. plugin->setCustomData(type, key, value, true);
  364. }
  365. else if (std::strcmp(msg, "set_chunk_data") == 0)
  366. {
  367. int pluginId;
  368. const char* cdata;
  369. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  370. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(cdata),);
  371. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  372. plugin->setChunkData(cdata);
  373. }
  374. else if (std::strcmp(msg, "prepare_for_save") == 0)
  375. {
  376. int pluginId;
  377. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  378. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  379. plugin->prepareForSave();
  380. }
  381. else if (std::strcmp(msg, "send_midi_note") == 0)
  382. {
  383. int pluginId;
  384. int channel, note, velocity;
  385. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  386. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(channel),);
  387. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(note),);
  388. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(velocity),);
  389. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS,);
  390. CARLA_SAFE_ASSERT_RETURN(note >= 0 && channel < MAX_MIDI_VALUE,);
  391. CARLA_SAFE_ASSERT_RETURN(velocity >= 0 && channel < MAX_MIDI_VALUE,);
  392. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  393. plugin->sendMidiSingleNote(uint8_t(channel), uint8_t(note), uint8_t(velocity), true, true, false);
  394. }
  395. else if (std::strcmp(msg, "show_custom_ui") == 0)
  396. {
  397. int pluginId;
  398. bool yesNo;
  399. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),);
  400. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo),);
  401. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  402. plugin->showCustomUI(yesNo);
  403. }
  404. else
  405. {
  406. carla_stderr("msgReceived : %s", msg);
  407. }
  408. }
  409. private:
  410. CarlaEngine* const fEngine;
  411. CarlaString fFilename;
  412. CarlaString fSampleRate;
  413. CarlaString fUiTitle;
  414. UiState fUiState;
  415. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNativeUI)
  416. };
  417. // -----------------------------------------------------------------------
  418. class CarlaEngineNative : public CarlaEngine
  419. {
  420. public:
  421. CarlaEngineNative(const NativeHostDescriptor* const host, const bool isPatchbay)
  422. : CarlaEngine(),
  423. pHost(host),
  424. fIsPatchbay(isPatchbay),
  425. fIsActive(false),
  426. fIsRunning(false),
  427. fUiServer(this)
  428. {
  429. carla_debug("CarlaEngineNative::CarlaEngineNative()");
  430. fTmpBuf[STR_MAX] = '\0';
  431. // set-up engine
  432. if (fIsPatchbay)
  433. {
  434. pData->options.processMode = ENGINE_PROCESS_MODE_PATCHBAY;
  435. pData->options.transportMode = ENGINE_TRANSPORT_MODE_PLUGIN;
  436. pData->options.forceStereo = false;
  437. pData->options.preferPluginBridges = false;
  438. pData->options.preferUiBridges = false;
  439. init("Carla-Patchbay");
  440. }
  441. else
  442. {
  443. pData->options.processMode = ENGINE_PROCESS_MODE_CONTINUOUS_RACK;
  444. pData->options.transportMode = ENGINE_TRANSPORT_MODE_PLUGIN;
  445. pData->options.forceStereo = true;
  446. pData->options.preferPluginBridges = false;
  447. pData->options.preferUiBridges = false;
  448. init("Carla-Rack");
  449. }
  450. setCallback(_ui_server_callback, this);
  451. }
  452. ~CarlaEngineNative() override
  453. {
  454. CARLA_ASSERT(! fIsActive);
  455. carla_debug("CarlaEngineNative::~CarlaEngineNative()");
  456. pData->aboutToClose = true;
  457. fIsRunning = false;
  458. removeAllPlugins();
  459. runPendingRtEvents();
  460. close();
  461. }
  462. protected:
  463. // -------------------------------------
  464. // CarlaEngine virtual calls
  465. bool init(const char* const clientName) override
  466. {
  467. carla_debug("CarlaEngineNative::init(\"%s\")", clientName);
  468. pData->bufferSize = pHost->get_buffer_size(pHost->handle);
  469. pData->sampleRate = pHost->get_sample_rate(pHost->handle);
  470. fIsRunning = true;
  471. CarlaEngine::init(clientName);
  472. return true;
  473. }
  474. bool isRunning() const noexcept override
  475. {
  476. return fIsRunning;
  477. }
  478. bool isOffline() const noexcept override
  479. {
  480. return pHost->is_offline(pHost->handle);
  481. }
  482. EngineType getType() const noexcept override
  483. {
  484. return kEngineTypePlugin;
  485. }
  486. const char* getCurrentDriverName() const noexcept override
  487. {
  488. return "Plugin";
  489. }
  490. // -------------------------------------------------------------------
  491. const char* renamePlugin(const unsigned int id, const char* const newName) override
  492. {
  493. if (const char* const retName = CarlaEngine::renamePlugin(id, newName))
  494. {
  495. uiServerCallback(ENGINE_CALLBACK_PLUGIN_RENAMED, id, 0, 0, 0.0f, retName);
  496. return retName;
  497. }
  498. return nullptr;
  499. }
  500. // -------------------------------------------------------------------
  501. void bufferSizeChanged(const uint32_t newBufferSize)
  502. {
  503. pData->bufferSize = newBufferSize;
  504. CarlaEngine::bufferSizeChanged(newBufferSize);
  505. }
  506. void sampleRateChanged(const double newSampleRate)
  507. {
  508. pData->sampleRate = newSampleRate;
  509. CarlaEngine::sampleRateChanged(newSampleRate);
  510. }
  511. // -------------------------------------------------------------------
  512. void uiServerSendPluginInfo(CarlaPlugin* const plugin)
  513. {
  514. const uint pluginId(plugin->getId());
  515. std::sprintf(fTmpBuf, "PLUGIN_INFO_%i\n", pluginId);
  516. fUiServer.writeMsg(fTmpBuf);
  517. std::sprintf(fTmpBuf, "%i:%i:%i:%li:%i:%i\n", plugin->getType(), plugin->getCategory(), plugin->getHints(), plugin->getUniqueId(), plugin->getOptionsAvailable(), plugin->getOptionsEnabled());
  518. fUiServer.writeMsg(fTmpBuf);
  519. if (const char* const filename = plugin->getFilename())
  520. {
  521. std::sprintf(fTmpBuf, "%s", filename);
  522. fUiServer.writeAndFixMsg(fTmpBuf);
  523. }
  524. else
  525. fUiServer.writeMsg("\n");
  526. if (const char* const name = plugin->getName())
  527. {
  528. std::sprintf(fTmpBuf, "%s", name);
  529. fUiServer.writeAndFixMsg(fTmpBuf);
  530. }
  531. else
  532. fUiServer.writeMsg("\n");
  533. if (const char* const iconName = plugin->getIconName())
  534. {
  535. std::sprintf(fTmpBuf, "%s", iconName);
  536. fUiServer.writeAndFixMsg(fTmpBuf);
  537. }
  538. else
  539. fUiServer.writeMsg("\n");
  540. plugin->getRealName(fTmpBuf);
  541. fUiServer.writeAndFixMsg(fTmpBuf);
  542. plugin->getLabel(fTmpBuf);
  543. fUiServer.writeAndFixMsg(fTmpBuf);
  544. plugin->getMaker(fTmpBuf);
  545. fUiServer.writeAndFixMsg(fTmpBuf);
  546. plugin->getCopyright(fTmpBuf);
  547. fUiServer.writeAndFixMsg(fTmpBuf);
  548. std::sprintf(fTmpBuf, "AUDIO_COUNT_%i:%i:%i\n", pluginId, plugin->getAudioInCount(), plugin->getAudioOutCount());
  549. fUiServer.writeMsg(fTmpBuf);
  550. std::sprintf(fTmpBuf, "MIDI_COUNT_%i:%i:%i\n", pluginId, plugin->getMidiInCount(), plugin->getMidiOutCount());
  551. fUiServer.writeMsg(fTmpBuf);
  552. }
  553. void uiServerSendPluginParameters(CarlaPlugin* const plugin)
  554. {
  555. const uint pluginId(plugin->getId());
  556. uint32_t ins, outs, count;
  557. plugin->getParameterCountInfo(ins, outs);
  558. count = plugin->getParameterCount();
  559. std::sprintf(fTmpBuf, "PARAMETER_COUNT_%i:%i:%i:%i\n", pluginId, ins, outs, count);
  560. fUiServer.writeMsg(fTmpBuf);
  561. for (uint32_t i=0; i<count; ++i)
  562. {
  563. const ParameterData& paramData(plugin->getParameterData(i));
  564. const ParameterRanges& paramRanges(plugin->getParameterRanges(i));
  565. std::sprintf(fTmpBuf, "PARAMETER_DATA_%i:%i\n", pluginId, i);
  566. fUiServer.writeMsg(fTmpBuf);
  567. std::sprintf(fTmpBuf, "%i:%i:%i:%i\n", paramData.type, paramData.hints, paramData.midiChannel, paramData.midiCC);
  568. fUiServer.writeMsg(fTmpBuf);
  569. plugin->getParameterName(i, fTmpBuf);
  570. fUiServer.writeAndFixMsg(fTmpBuf);
  571. plugin->getParameterUnit(i, fTmpBuf);
  572. fUiServer.writeAndFixMsg(fTmpBuf);
  573. std::sprintf(fTmpBuf, "PARAMETER_RANGES_%i:%i\n", pluginId, i);
  574. fUiServer.writeMsg(fTmpBuf);
  575. std::sprintf(fTmpBuf, "%f:%f:%f:%f:%f:%f\n", paramRanges.def, paramRanges.min, paramRanges.max, paramRanges.step, paramRanges.stepSmall, paramRanges.stepLarge);
  576. fUiServer.writeMsg(fTmpBuf);
  577. std::sprintf(fTmpBuf, "PARAMVAL_%i:%i\n", pluginId, i);
  578. fUiServer.writeMsg(fTmpBuf);
  579. std::sprintf(fTmpBuf, "%f\n", plugin->getParameterValue(i));
  580. fUiServer.writeMsg(fTmpBuf);
  581. }
  582. }
  583. void uiServerSendPluginPrograms(CarlaPlugin* const plugin)
  584. {
  585. const uint pluginId(plugin->getId());
  586. uint32_t count = plugin->getProgramCount();
  587. std::sprintf(fTmpBuf, "PROGRAM_COUNT_%i:%i:%i\n", pluginId, count, plugin->getCurrentProgram());
  588. fUiServer.writeMsg(fTmpBuf);
  589. for (uint32_t i=0; i<count; ++i)
  590. {
  591. std::sprintf(fTmpBuf, "PROGRAM_NAME_%i:%i\n", pluginId, i);
  592. fUiServer.writeMsg(fTmpBuf);
  593. plugin->getProgramName(i, fTmpBuf);
  594. fUiServer.writeAndFixMsg(fTmpBuf);
  595. }
  596. count = plugin->getMidiProgramCount();
  597. std::sprintf(fTmpBuf, "MIDI_PROGRAM_COUNT_%i:%i:%i\n", pluginId, count, plugin->getCurrentMidiProgram());
  598. fUiServer.writeMsg(fTmpBuf);
  599. for (uint32_t i=0; i<count; ++i)
  600. {
  601. std::sprintf(fTmpBuf, "MIDI_PROGRAM_DATA_%i:%i\n", pluginId, i);
  602. fUiServer.writeMsg(fTmpBuf);
  603. const MidiProgramData& mpData(plugin->getMidiProgramData(i));
  604. std::sprintf(fTmpBuf, "%i:%i\n", mpData.bank, mpData.program);
  605. fUiServer.writeMsg(fTmpBuf);
  606. std::sprintf(fTmpBuf, "%s", mpData.name);
  607. fUiServer.writeAndFixMsg(fTmpBuf);
  608. }
  609. }
  610. void uiServerCallback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const float value3, const char* const valueStr)
  611. {
  612. if (! fIsRunning)
  613. return;
  614. if (! fUiServer.isOk())
  615. return;
  616. CarlaPlugin* plugin;
  617. switch (action)
  618. {
  619. case ENGINE_CALLBACK_RELOAD_INFO:
  620. plugin = getPlugin(pluginId);
  621. if (plugin != nullptr && plugin->isEnabled())
  622. {
  623. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  624. uiServerSendPluginInfo(plugin);
  625. }
  626. break;
  627. case ENGINE_CALLBACK_RELOAD_PARAMETERS:
  628. plugin = getPlugin(pluginId);
  629. if (plugin != nullptr && plugin->isEnabled())
  630. {
  631. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  632. uiServerSendPluginParameters(plugin);
  633. }
  634. break;
  635. case ENGINE_CALLBACK_RELOAD_PROGRAMS:
  636. plugin = getPlugin(pluginId);
  637. if (plugin != nullptr && plugin->isEnabled())
  638. {
  639. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  640. uiServerSendPluginPrograms(plugin);
  641. }
  642. break;
  643. case ENGINE_CALLBACK_RELOAD_ALL:
  644. case ENGINE_CALLBACK_PLUGIN_ADDED:
  645. plugin = getPlugin(pluginId);
  646. if (plugin != nullptr && plugin->isEnabled())
  647. {
  648. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  649. uiServerSendPluginInfo(plugin);
  650. uiServerSendPluginParameters(plugin);
  651. uiServerSendPluginPrograms(plugin);
  652. }
  653. break;
  654. default:
  655. break;
  656. }
  657. std::sprintf(fTmpBuf, "ENGINE_CALLBACK_%i\n", int(action));
  658. fUiServer.writeMsg(fTmpBuf);
  659. std::sprintf(fTmpBuf, "%u\n", pluginId);
  660. fUiServer.writeMsg(fTmpBuf);
  661. std::sprintf(fTmpBuf, "%i\n", value1);
  662. fUiServer.writeMsg(fTmpBuf);
  663. std::sprintf(fTmpBuf, "%i\n", value2);
  664. fUiServer.writeMsg(fTmpBuf);
  665. std::sprintf(fTmpBuf, "%f\n", value3);
  666. fUiServer.writeMsg(fTmpBuf);
  667. fUiServer.writeAndFixMsg(valueStr);
  668. }
  669. // -------------------------------------------------------------------
  670. // Plugin parameter calls
  671. uint32_t getParameterCount() const
  672. {
  673. if (CarlaPlugin* const plugin = _getFirstPlugin())
  674. return plugin->getParameterCount();
  675. return 0;
  676. }
  677. const NativeParameter* getParameterInfo(const uint32_t index) const
  678. {
  679. if (CarlaPlugin* const plugin = _getFirstPlugin())
  680. {
  681. if (index < plugin->getParameterCount())
  682. {
  683. static NativeParameter param;
  684. static char strBufName[STR_MAX+1];
  685. static char strBufUnit[STR_MAX+1];
  686. const ParameterData& paramData(plugin->getParameterData(index));
  687. const ParameterRanges& paramRanges(plugin->getParameterRanges(index));
  688. plugin->getParameterName(index, strBufName);
  689. plugin->getParameterUnit(index, strBufUnit);
  690. unsigned int hints = 0x0;
  691. if (paramData.hints & PARAMETER_IS_BOOLEAN)
  692. hints |= ::PARAMETER_IS_BOOLEAN;
  693. if (paramData.hints & PARAMETER_IS_INTEGER)
  694. hints |= ::PARAMETER_IS_INTEGER;
  695. if (paramData.hints & PARAMETER_IS_LOGARITHMIC)
  696. hints |= ::PARAMETER_IS_LOGARITHMIC;
  697. if (paramData.hints & PARAMETER_IS_AUTOMABLE)
  698. hints |= ::PARAMETER_IS_AUTOMABLE;
  699. if (paramData.hints & PARAMETER_USES_SAMPLERATE)
  700. hints |= ::PARAMETER_USES_SAMPLE_RATE;
  701. if (paramData.hints & PARAMETER_USES_SCALEPOINTS)
  702. hints |= ::PARAMETER_USES_SCALEPOINTS;
  703. if (paramData.hints & PARAMETER_USES_CUSTOM_TEXT)
  704. hints |= ::PARAMETER_USES_CUSTOM_TEXT;
  705. if (paramData.type == PARAMETER_INPUT || paramData.type == PARAMETER_OUTPUT)
  706. {
  707. if (paramData.hints & PARAMETER_IS_ENABLED)
  708. hints |= ::PARAMETER_IS_ENABLED;
  709. if (paramData.type == PARAMETER_OUTPUT)
  710. hints |= ::PARAMETER_IS_OUTPUT;
  711. }
  712. param.hints = static_cast<NativeParameterHints>(hints);
  713. param.name = strBufName;
  714. param.unit = strBufUnit;
  715. param.ranges.def = paramRanges.def;
  716. param.ranges.min = paramRanges.min;
  717. param.ranges.max = paramRanges.max;
  718. param.ranges.step = paramRanges.step;
  719. param.ranges.stepSmall = paramRanges.stepSmall;
  720. param.ranges.stepLarge = paramRanges.stepLarge;
  721. param.scalePointCount = 0; // TODO
  722. param.scalePoints = nullptr;
  723. return &param;
  724. }
  725. }
  726. return nullptr;
  727. }
  728. float getParameterValue(const uint32_t index) const
  729. {
  730. if (CarlaPlugin* const plugin = _getFirstPlugin())
  731. {
  732. if (index < plugin->getParameterCount())
  733. return plugin->getParameterValue(index);
  734. }
  735. return 0.0f;
  736. }
  737. const char* getParameterText(const uint32_t index, const float value) const
  738. {
  739. if (CarlaPlugin* const plugin = _getFirstPlugin())
  740. {
  741. if (index < plugin->getParameterCount())
  742. {
  743. static char strBuf[STR_MAX+1];
  744. carla_zeroChar(strBuf, STR_MAX+1);
  745. plugin->getParameterText(index, value, strBuf);
  746. return strBuf;
  747. }
  748. }
  749. return nullptr;
  750. }
  751. // -------------------------------------------------------------------
  752. // Plugin midi-program calls
  753. uint32_t getMidiProgramCount() const
  754. {
  755. if (CarlaPlugin* const plugin = _getFirstPlugin())
  756. return plugin->getMidiProgramCount();
  757. return 0;
  758. }
  759. const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const
  760. {
  761. if (CarlaPlugin* const plugin = _getFirstPlugin())
  762. {
  763. if (index < plugin->getMidiProgramCount())
  764. {
  765. static NativeMidiProgram midiProg;
  766. {
  767. const MidiProgramData& midiProgData(plugin->getMidiProgramData(index));
  768. midiProg.bank = midiProgData.bank;
  769. midiProg.program = midiProgData.program;
  770. midiProg.name = midiProgData.name;
  771. }
  772. return &midiProg;
  773. }
  774. }
  775. return nullptr;
  776. }
  777. // -------------------------------------------------------------------
  778. // Plugin state calls
  779. void setParameterValue(const uint32_t index, const float value)
  780. {
  781. if (CarlaPlugin* const plugin = _getFirstPlugin())
  782. {
  783. if (index < plugin->getParameterCount())
  784. plugin->setParameterValue(index, value, false, false, false);
  785. }
  786. }
  787. void setMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program)
  788. {
  789. if (CarlaPlugin* const plugin = _getFirstPlugin())
  790. plugin->setMidiProgramById(bank, program, false, false, false);
  791. }
  792. // -------------------------------------------------------------------
  793. // Plugin process calls
  794. void activate()
  795. {
  796. #if 0
  797. for (uint32_t i=0; i < pData->curPluginCount; ++i)
  798. {
  799. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  800. if (plugin == nullptr || ! plugin->isEnabled())
  801. continue;
  802. plugin->setActive(true, true, false);
  803. }
  804. #endif
  805. fIsActive = true;
  806. }
  807. void deactivate()
  808. {
  809. fIsActive = false;
  810. #if 0
  811. for (uint32_t i=0; i < pData->curPluginCount; ++i)
  812. {
  813. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  814. if (plugin == nullptr || ! plugin->isEnabled())
  815. continue;
  816. plugin->setActive(false, true, false);
  817. }
  818. #endif
  819. // just in case
  820. runPendingRtEvents();
  821. }
  822. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount)
  823. {
  824. if (pData->curPluginCount == 0 && ! fIsPatchbay)
  825. {
  826. FLOAT_COPY(outBuffer[0], inBuffer[0], frames);
  827. FLOAT_COPY(outBuffer[1], inBuffer[1], frames);
  828. return runPendingRtEvents();;
  829. }
  830. // ---------------------------------------------------------------
  831. // Time Info
  832. const NativeTimeInfo* const timeInfo(pHost->get_time_info(pHost->handle));
  833. pData->timeInfo.playing = timeInfo->playing;
  834. pData->timeInfo.frame = timeInfo->frame;
  835. pData->timeInfo.usecs = timeInfo->usecs;
  836. pData->timeInfo.valid = 0x0;
  837. if (timeInfo->bbt.valid)
  838. {
  839. pData->timeInfo.valid |= EngineTimeInfo::kValidBBT;
  840. pData->timeInfo.bbt.bar = timeInfo->bbt.bar;
  841. pData->timeInfo.bbt.beat = timeInfo->bbt.beat;
  842. pData->timeInfo.bbt.tick = timeInfo->bbt.tick;
  843. pData->timeInfo.bbt.barStartTick = timeInfo->bbt.barStartTick;
  844. pData->timeInfo.bbt.beatsPerBar = timeInfo->bbt.beatsPerBar;
  845. pData->timeInfo.bbt.beatType = timeInfo->bbt.beatType;
  846. pData->timeInfo.bbt.ticksPerBeat = timeInfo->bbt.ticksPerBeat;
  847. pData->timeInfo.bbt.beatsPerMinute = timeInfo->bbt.beatsPerMinute;
  848. }
  849. // ---------------------------------------------------------------
  850. // initialize events
  851. carla_zeroStruct<EngineEvent>(pData->bufEvents.in, kEngineMaxInternalEventCount);
  852. carla_zeroStruct<EngineEvent>(pData->bufEvents.out, kEngineMaxInternalEventCount);
  853. // ---------------------------------------------------------------
  854. // events input (before processing)
  855. {
  856. uint32_t engineEventIndex = 0;
  857. for (uint32_t i=0; i < midiEventCount && engineEventIndex < kEngineMaxInternalEventCount; ++i)
  858. {
  859. const NativeMidiEvent& midiEvent(midiEvents[i]);
  860. EngineEvent& engineEvent(pData->bufEvents.in[engineEventIndex++]);
  861. engineEvent.time = midiEvent.time;
  862. engineEvent.fillFromMidiData(midiEvent.size, midiEvent.data);
  863. if (engineEventIndex >= kEngineMaxInternalEventCount)
  864. break;
  865. }
  866. }
  867. if (fIsPatchbay)
  868. {
  869. // -----------------------------------------------------------
  870. // create audio buffers
  871. //float* inBuf[2] = { inBuffer[0], inBuffer[1] };
  872. //float* outBuf[2] = { outBuffer[0], outBuffer[1] };
  873. //uint32_t bufCount[2] = { 2, 2 };
  874. // -----------------------------------------------------------
  875. // process
  876. //pData->processPatchbay(inBuf, outBuf, bufCount, frames, isOffline());
  877. }
  878. else
  879. {
  880. // -----------------------------------------------------------
  881. // create audio buffers
  882. float* inBuf[2] = { inBuffer[0], inBuffer[1] };
  883. float* outBuf[2] = { outBuffer[0], outBuffer[1] };
  884. // -----------------------------------------------------------
  885. // process
  886. pData->processRack(inBuf, outBuf, frames, isOffline());
  887. }
  888. // ---------------------------------------------------------------
  889. // events output (after processing)
  890. carla_zeroStruct<EngineEvent>(pData->bufEvents.in, kEngineMaxInternalEventCount);
  891. {
  892. NativeMidiEvent midiEvent;
  893. for (uint32_t i=0; i < kEngineMaxInternalEventCount; ++i)
  894. {
  895. const EngineEvent& engineEvent(pData->bufEvents.out[i]);
  896. if (engineEvent.type == kEngineEventTypeNull)
  897. break;
  898. midiEvent.time = engineEvent.time;
  899. if (engineEvent.type == CarlaBackend::kEngineEventTypeControl)
  900. {
  901. midiEvent.port = 0;
  902. engineEvent.ctrl.dumpToMidiData(engineEvent.channel, midiEvent.size, midiEvent.data);
  903. }
  904. else if (engineEvent.type == kEngineEventTypeMidi)
  905. {
  906. if (engineEvent.midi.size > 4 || engineEvent.midi.dataExt != nullptr)
  907. continue;
  908. midiEvent.port = engineEvent.midi.port;
  909. midiEvent.size = engineEvent.midi.size;
  910. midiEvent.data[0] = static_cast<uint8_t>(engineEvent.midi.data[0] + engineEvent.channel);
  911. for (uint8_t j=1; j < midiEvent.size; ++j)
  912. midiEvent.data[j] = engineEvent.midi.data[j];
  913. }
  914. else
  915. {
  916. carla_stderr("Unknown event type...");
  917. continue;
  918. }
  919. pHost->write_midi_event(pHost->handle, &midiEvent);
  920. }
  921. }
  922. runPendingRtEvents();
  923. }
  924. // -------------------------------------------------------------------
  925. // Plugin UI calls
  926. void uiShow(const bool show)
  927. {
  928. if (show)
  929. {
  930. fUiServer.setData("/home/falktx/FOSS/GIT-mine/Carla/source/carla-plugin", pData->sampleRate, pHost->uiName);
  931. fUiServer.start();
  932. for (uint i=0; i < pData->curPluginCount; ++i)
  933. {
  934. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  935. if (plugin != nullptr && plugin->isEnabled())
  936. {
  937. uiServerCallback(ENGINE_CALLBACK_PLUGIN_ADDED, i, 0, 0, 0.0f, plugin->getName());
  938. }
  939. }
  940. }
  941. else
  942. {
  943. fUiServer.stop();
  944. }
  945. }
  946. void uiIdle()
  947. {
  948. CarlaEngine::idle();
  949. fUiServer.idle();
  950. if (! fUiServer.isOk())
  951. return;
  952. for (uint i=0; i < pData->curPluginCount; ++i)
  953. {
  954. const EnginePluginData& plugData(pData->plugins[i]);
  955. const CarlaPlugin* const plugin(pData->plugins[i].plugin);
  956. std::sprintf(fTmpBuf, "PEAKS_%i\n", i);
  957. fUiServer.writeMsg(fTmpBuf);
  958. std::sprintf(fTmpBuf, "%f:%f:%f:%f\n", plugData.insPeak[0], plugData.insPeak[1], plugData.outsPeak[0], plugData.outsPeak[1]);
  959. fUiServer.writeMsg(fTmpBuf);
  960. for (uint32_t j=0, count=plugin->getParameterCount(); j < count; ++j)
  961. {
  962. if (plugin->isParameterOutput(j))
  963. continue;
  964. std::sprintf(fTmpBuf, "PARAMVAL_%i:%i\n", i, j);
  965. fUiServer.writeMsg(fTmpBuf);
  966. std::sprintf(fTmpBuf, "%f\n", plugin->getParameterValue(j));
  967. fUiServer.writeMsg(fTmpBuf);
  968. }
  969. }
  970. switch (fUiServer.getAndResetUiState())
  971. {
  972. case CarlaEngineNativeUI::UiNone:
  973. case CarlaEngineNativeUI::UiShow:
  974. break;
  975. case CarlaEngineNativeUI::UiCrashed:
  976. pHost->dispatcher(pHost->handle, HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f);
  977. break;
  978. case CarlaEngineNativeUI::UiHide:
  979. pHost->ui_closed(pHost->handle);
  980. break;
  981. }
  982. }
  983. // -------------------------------------------------------------------
  984. // Plugin state calls
  985. char* getState() const
  986. {
  987. QString string;
  988. QTextStream out(&string);
  989. out << "<?xml version='1.0' encoding='UTF-8'?>\n";
  990. out << "<!DOCTYPE CARLA-PROJECT>\n";
  991. out << "<CARLA-PROJECT VERSION='2.0'>\n";
  992. bool firstPlugin = true;
  993. char strBuf[STR_MAX+1];
  994. for (unsigned int i=0; i < pData->curPluginCount; ++i)
  995. {
  996. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  997. if (plugin != nullptr && plugin->isEnabled())
  998. {
  999. if (! firstPlugin)
  1000. out << "\n";
  1001. strBuf[0] = '\0';
  1002. plugin->getRealName(strBuf);
  1003. if (strBuf[0] != '\0')
  1004. out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true));
  1005. QString content;
  1006. fillXmlStringFromSaveState(content, plugin->getSaveState());
  1007. out << " <Plugin>\n";
  1008. out << content;
  1009. out << " </Plugin>\n";
  1010. firstPlugin = false;
  1011. }
  1012. }
  1013. out << "</CARLA-PROJECT>\n";
  1014. return strdup(string.toUtf8().constData());
  1015. }
  1016. void setState(const char* const data)
  1017. {
  1018. QDomDocument xml;
  1019. xml.setContent(QString(data));
  1020. QDomNode xmlNode(xml.documentElement());
  1021. if (xmlNode.toElement().tagName().compare("carla-project", Qt::CaseInsensitive) != 0)
  1022. {
  1023. carla_stderr2("Not a valid Carla project");
  1024. return;
  1025. }
  1026. //bool pluginsAdded = false;
  1027. for (QDomNode node = xmlNode.firstChild(); ! node.isNull(); node = node.nextSibling())
  1028. {
  1029. if (node.toElement().tagName().compare("plugin", Qt::CaseInsensitive) == 0)
  1030. {
  1031. SaveState saveState;
  1032. fillSaveStateFromXmlNode(saveState, node);
  1033. CARLA_SAFE_ASSERT_CONTINUE(saveState.type != nullptr)
  1034. const void* extraStuff = nullptr;
  1035. // check if using GIG, SF2 or SFZ 16outs
  1036. static const char kUse16OutsSuffix[] = " (16 outs)";
  1037. if (CarlaString(saveState.label).endsWith(kUse16OutsSuffix))
  1038. {
  1039. if (std::strcmp(saveState.type, "GIG") == 0 || std::strcmp(saveState.type, "SF2") == 0)
  1040. extraStuff = "true";
  1041. }
  1042. // TODO - proper find&load plugins
  1043. if (addPlugin(getPluginTypeFromString(saveState.type), saveState.binary, saveState.name, saveState.label, extraStuff))
  1044. {
  1045. if (CarlaPlugin* const plugin = getPlugin(pData->curPluginCount-1))
  1046. plugin->loadSaveState(saveState);
  1047. }
  1048. //pluginsAdded = true;
  1049. }
  1050. }
  1051. //if (pluginsAdded)
  1052. // pHost->dispatcher(pHost->handle, HOST_OPCODE_RELOAD_ALL, 0, 0, nullptr, 0.0f);
  1053. }
  1054. // -------------------------------------------------------------------
  1055. public:
  1056. #define handlePtr ((CarlaEngineNative*)handle)
  1057. static NativePluginHandle _instantiateRack(const NativeHostDescriptor* host)
  1058. {
  1059. return new CarlaEngineNative(host, false);
  1060. }
  1061. #ifdef HAVE_JUCE
  1062. static NativePluginHandle _instantiatePatchbay(const NativeHostDescriptor* host)
  1063. {
  1064. return new CarlaEngineNative(host, true);
  1065. }
  1066. #endif
  1067. static void _cleanup(NativePluginHandle handle)
  1068. {
  1069. delete handlePtr;
  1070. }
  1071. static uint32_t _get_parameter_count(NativePluginHandle handle)
  1072. {
  1073. return handlePtr->getParameterCount();
  1074. }
  1075. static const NativeParameter* _get_parameter_info(NativePluginHandle handle, uint32_t index)
  1076. {
  1077. return handlePtr->getParameterInfo(index);
  1078. }
  1079. static float _get_parameter_value(NativePluginHandle handle, uint32_t index)
  1080. {
  1081. return handlePtr->getParameterValue(index);
  1082. }
  1083. static const char* _get_parameter_text(NativePluginHandle handle, uint32_t index, float value)
  1084. {
  1085. return handlePtr->getParameterText(index, value);
  1086. }
  1087. static uint32_t _get_midi_program_count(NativePluginHandle handle)
  1088. {
  1089. return handlePtr->getMidiProgramCount();
  1090. }
  1091. static const NativeMidiProgram* _get_midi_program_info(NativePluginHandle handle, uint32_t index)
  1092. {
  1093. return handlePtr->getMidiProgramInfo(index);
  1094. }
  1095. static void _set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  1096. {
  1097. handlePtr->setParameterValue(index, value);
  1098. }
  1099. static void _set_midi_program(NativePluginHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
  1100. {
  1101. handlePtr->setMidiProgram(channel, bank, program);
  1102. }
  1103. static void _ui_show(NativePluginHandle handle, bool show)
  1104. {
  1105. handlePtr->uiShow(show);
  1106. }
  1107. static void _ui_idle(NativePluginHandle handle)
  1108. {
  1109. handlePtr->uiIdle();
  1110. }
  1111. static void _activate(NativePluginHandle handle)
  1112. {
  1113. handlePtr->activate();
  1114. }
  1115. static void _deactivate(NativePluginHandle handle)
  1116. {
  1117. handlePtr->deactivate();
  1118. }
  1119. static void _process(NativePluginHandle handle, float** inBuffer, float** outBuffer, const uint32_t frames, const NativeMidiEvent* midiEvents, uint32_t midiEventCount)
  1120. {
  1121. handlePtr->process(inBuffer, outBuffer, frames, midiEvents, midiEventCount);
  1122. }
  1123. static char* _get_state(NativePluginHandle handle)
  1124. {
  1125. return handlePtr->getState();
  1126. }
  1127. static void _set_state(NativePluginHandle handle, const char* data)
  1128. {
  1129. handlePtr->setState(data);
  1130. }
  1131. static intptr_t _dispatcher(NativePluginHandle handle, NativePluginDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
  1132. {
  1133. switch(opcode)
  1134. {
  1135. case PLUGIN_OPCODE_NULL:
  1136. return 0;
  1137. case PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
  1138. CARLA_SAFE_ASSERT_RETURN(value > 0, 0);
  1139. handlePtr->bufferSizeChanged(static_cast<uint32_t>(value));
  1140. return 0;
  1141. case PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
  1142. handlePtr->sampleRateChanged(static_cast<double>(opt));
  1143. return 0;
  1144. case PLUGIN_OPCODE_OFFLINE_CHANGED:
  1145. handlePtr->offlineModeChanged(value != 0);
  1146. return 0;
  1147. case PLUGIN_OPCODE_UI_NAME_CHANGED:
  1148. //handlePtr->uiNameChanged(static_cast<const char*>(ptr));
  1149. return 0;
  1150. }
  1151. return 0;
  1152. // unused
  1153. (void)index;
  1154. (void)ptr;
  1155. }
  1156. // -------------------------------------------------------------------
  1157. static void _ui_server_callback(void* handle, EngineCallbackOpcode action, uint pluginId, int value1, int value2, float value3, const char* valueStr)
  1158. {
  1159. handlePtr->uiServerCallback(action, pluginId, value1, value2, value3, valueStr);
  1160. }
  1161. // -------------------------------------------------------------------
  1162. #undef handlePtr
  1163. private:
  1164. const NativeHostDescriptor* const pHost;
  1165. const bool fIsPatchbay; // rack if false
  1166. bool fIsActive, fIsRunning;
  1167. CarlaEngineNativeUI fUiServer;
  1168. char fTmpBuf[STR_MAX+1];
  1169. CarlaPlugin* _getFirstPlugin() const noexcept
  1170. {
  1171. if (pData->curPluginCount == 0 || pData->plugins == nullptr)
  1172. return nullptr;
  1173. CarlaPlugin* const plugin(pData->plugins[0].plugin);
  1174. if (plugin == nullptr || ! plugin->isEnabled())
  1175. return nullptr;
  1176. return pData->plugins[0].plugin;
  1177. }
  1178. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNative)
  1179. };
  1180. // -----------------------------------------------------------------------
  1181. static const NativePluginDescriptor carlaRackDesc = {
  1182. /* category */ ::PLUGIN_CATEGORY_OTHER,
  1183. /* hints */ static_cast<NativePluginHints>(::PLUGIN_IS_SYNTH|::PLUGIN_HAS_UI|::PLUGIN_NEEDS_FIXED_BUFFERS|::PLUGIN_NEEDS_SINGLE_THREAD|::PLUGIN_USES_STATE|::PLUGIN_USES_TIME),
  1184. /* supports */ static_cast<NativePluginSupports>(::PLUGIN_SUPPORTS_EVERYTHING),
  1185. /* audioIns */ 2,
  1186. /* audioOuts */ 2,
  1187. /* midiIns */ 1,
  1188. /* midiOuts */ 1,
  1189. /* paramIns */ 0,
  1190. /* paramOuts */ 0,
  1191. /* name */ "Carla-Rack",
  1192. /* label */ "carla-rack",
  1193. /* maker */ "falkTX",
  1194. /* copyright */ "GNU GPL v2+",
  1195. CarlaEngineNative::_instantiateRack,
  1196. CarlaEngineNative::_cleanup,
  1197. CarlaEngineNative::_get_parameter_count,
  1198. CarlaEngineNative::_get_parameter_info,
  1199. CarlaEngineNative::_get_parameter_value,
  1200. CarlaEngineNative::_get_parameter_text,
  1201. CarlaEngineNative::_get_midi_program_count,
  1202. CarlaEngineNative::_get_midi_program_info,
  1203. CarlaEngineNative::_set_parameter_value,
  1204. CarlaEngineNative::_set_midi_program,
  1205. /* _set_custom_data */ nullptr,
  1206. CarlaEngineNative::_ui_show,
  1207. CarlaEngineNative::_ui_idle,
  1208. /* _ui_set_parameter_value */ nullptr,
  1209. /* _ui_set_midi_program */ nullptr,
  1210. /* _ui_set_custom_data */ nullptr,
  1211. CarlaEngineNative::_activate,
  1212. CarlaEngineNative::_deactivate,
  1213. CarlaEngineNative::_process,
  1214. CarlaEngineNative::_get_state,
  1215. CarlaEngineNative::_set_state,
  1216. CarlaEngineNative::_dispatcher
  1217. };
  1218. #ifdef HAVE_JUCE
  1219. static const NativePluginDescriptor carlaPatchbayDesc = {
  1220. /* category */ ::PLUGIN_CATEGORY_OTHER,
  1221. /* hints */ static_cast<NativePluginHints>(::PLUGIN_IS_SYNTH|::PLUGIN_HAS_UI|::PLUGIN_NEEDS_FIXED_BUFFERS|::PLUGIN_NEEDS_SINGLE_THREAD|::PLUGIN_USES_STATE|::PLUGIN_USES_TIME),
  1222. /* supports */ static_cast<NativePluginSupports>(::PLUGIN_SUPPORTS_EVERYTHING),
  1223. /* audioIns */ 2,
  1224. /* audioOuts */ 2,
  1225. /* midiIns */ 1,
  1226. /* midiOuts */ 1,
  1227. /* paramIns */ 0,
  1228. /* paramOuts */ 0,
  1229. /* name */ "Carla-Patchbay",
  1230. /* label */ "carla-patchbay",
  1231. /* maker */ "falkTX",
  1232. /* copyright */ "GNU GPL v2+",
  1233. CarlaEngineNative::_instantiatePatchbay,
  1234. CarlaEngineNative::_cleanup,
  1235. CarlaEngineNative::_get_parameter_count,
  1236. CarlaEngineNative::_get_parameter_info,
  1237. CarlaEngineNative::_get_parameter_value,
  1238. CarlaEngineNative::_get_parameter_text,
  1239. CarlaEngineNative::_get_midi_program_count,
  1240. CarlaEngineNative::_get_midi_program_info,
  1241. CarlaEngineNative::_set_parameter_value,
  1242. CarlaEngineNative::_set_midi_program,
  1243. /* _set_custom_data */ nullptr,
  1244. CarlaEngineNative::_ui_show,
  1245. CarlaEngineNative::_ui_idle,
  1246. /* _ui_set_parameter_value */ nullptr,
  1247. /* _ui_set_midi_program */ nullptr,
  1248. /* _ui_set_custom_data */ nullptr,
  1249. CarlaEngineNative::_activate,
  1250. CarlaEngineNative::_deactivate,
  1251. CarlaEngineNative::_process,
  1252. CarlaEngineNative::_get_state,
  1253. CarlaEngineNative::_set_state,
  1254. CarlaEngineNative::_dispatcher
  1255. };
  1256. #endif
  1257. // -----------------------------------------------------------------------
  1258. CARLA_BACKEND_END_NAMESPACE
  1259. CARLA_EXPORT
  1260. void carla_register_native_plugin_carla()
  1261. {
  1262. CARLA_BACKEND_USE_NAMESPACE
  1263. carla_register_native_plugin(&carlaRackDesc);
  1264. #ifdef HAVE_JUCE
  1265. carla_register_native_plugin(&carlaPatchbayDesc);
  1266. #endif
  1267. }
  1268. // -----------------------------------------------------------------------
  1269. // Extra stuff for linking purposes
  1270. #ifdef CARLA_PLUGIN_EXPORT
  1271. CARLA_BACKEND_START_NAMESPACE
  1272. CarlaEngine* CarlaEngine::newJack() { return nullptr; }
  1273. CarlaEngine* CarlaEngine::newRtAudio(const AudioApi) { return nullptr; }
  1274. unsigned int CarlaEngine::getRtAudioApiCount() { return 0; }
  1275. const char* CarlaEngine::getRtAudioApiName(const unsigned int) { return nullptr; }
  1276. const char* const* CarlaEngine::getRtAudioApiDeviceNames(const unsigned int) { return nullptr; }
  1277. const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const unsigned int, const char* const) { return nullptr; }
  1278. # ifdef HAVE_JUCE
  1279. CarlaEngine* CarlaEngine::newJuce(const AudioApi) { return nullptr; }
  1280. unsigned int CarlaEngine::getJuceApiCount() { return 0; }
  1281. const char* CarlaEngine::getJuceApiName(const unsigned int) { return nullptr; }
  1282. const char* const* CarlaEngine::getJuceApiDeviceNames(const unsigned int) { return nullptr; }
  1283. const EngineDriverDeviceInfo* CarlaEngine::getJuceDeviceInfo(const unsigned int, const char* const) { return nullptr; }
  1284. # endif
  1285. CARLA_BACKEND_END_NAMESPACE
  1286. #endif
  1287. // -----------------------------------------------------------------------