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.

1551 lines
49KB

  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2014 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. /* TODO:
  18. * - complete processRack(): carefully add to input, sorted events
  19. * - implement processPatchbay()
  20. * - implement oscSend_control_switch_plugins()
  21. * - proper find&load plugins
  22. * - something about the peaks?
  23. * - patchbayDisconnect should return false sometimes
  24. */
  25. #include "CarlaEngineInternal.hpp"
  26. #include "CarlaPlugin.hpp"
  27. #include "CarlaBackendUtils.hpp"
  28. #include "CarlaEngineUtils.hpp"
  29. #include "CarlaMathUtils.hpp"
  30. #include "CarlaStateUtils.hpp"
  31. #include "CarlaMIDI.h"
  32. #include "jackbridge/JackBridge.hpp"
  33. #include "juce_core.h"
  34. using juce::File;
  35. using juce::MemoryOutputStream;
  36. using juce::ScopedPointer;
  37. using juce::String;
  38. using juce::XmlDocument;
  39. using juce::XmlElement;
  40. CARLA_BACKEND_START_NAMESPACE
  41. // -----------------------------------------------------------------------
  42. // Carla Engine
  43. CarlaEngine::CarlaEngine()
  44. : pData(new ProtectedData(this))
  45. {
  46. carla_debug("CarlaEngine::CarlaEngine()");
  47. }
  48. CarlaEngine::~CarlaEngine()
  49. {
  50. carla_debug("CarlaEngine::~CarlaEngine()");
  51. delete pData;
  52. }
  53. // -----------------------------------------------------------------------
  54. // Static calls
  55. uint CarlaEngine::getDriverCount()
  56. {
  57. carla_debug("CarlaEngine::getDriverCount()");
  58. uint count = 0;
  59. if (jackbridge_is_ok())
  60. count += 1;
  61. #ifndef BUILD_BRIDGE
  62. count += getRtAudioApiCount();
  63. count += getJuceApiCount();
  64. #endif
  65. return count;
  66. }
  67. const char* CarlaEngine::getDriverName(const uint index2)
  68. {
  69. carla_debug("CarlaEngine::getDriverName(%i)", index2);
  70. uint index(index2);
  71. if (jackbridge_is_ok() && index-- == 0)
  72. return "JACK";
  73. #ifndef BUILD_BRIDGE
  74. if (index < getRtAudioApiCount())
  75. return getRtAudioApiName(index);
  76. index -= getRtAudioApiCount();
  77. if (index < getJuceApiCount())
  78. return getJuceApiName(index);
  79. #endif
  80. carla_stderr("CarlaEngine::getDriverName(%i) - invalid index", index2);
  81. return nullptr;
  82. }
  83. const char* const* CarlaEngine::getDriverDeviceNames(const uint index2)
  84. {
  85. carla_debug("CarlaEngine::getDriverDeviceNames(%i)", index2);
  86. uint index(index2);
  87. if (jackbridge_is_ok() && index-- == 0)
  88. {
  89. static const char* ret[3] = { "Auto-Connect OFF", "Auto-Connect ON", nullptr };
  90. return ret;
  91. }
  92. #ifndef BUILD_BRIDGE
  93. if (index < getRtAudioApiCount())
  94. return getRtAudioApiDeviceNames(index);
  95. index -= getRtAudioApiCount();
  96. if (index < getJuceApiCount())
  97. return getJuceApiDeviceNames(index);
  98. #endif
  99. carla_stderr("CarlaEngine::getDriverDeviceNames(%i) - invalid index", index2);
  100. return nullptr;
  101. }
  102. const EngineDriverDeviceInfo* CarlaEngine::getDriverDeviceInfo(const uint index2, const char* const deviceName)
  103. {
  104. carla_debug("CarlaEngine::getDriverDeviceInfo(%i, \"%s\")", index2, deviceName);
  105. uint index(index2);
  106. if (jackbridge_is_ok() && index-- == 0)
  107. {
  108. static uint32_t bufSizes[11] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0 };
  109. static EngineDriverDeviceInfo devInfo;
  110. devInfo.hints = ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE;
  111. devInfo.bufferSizes = bufSizes;
  112. devInfo.sampleRates = nullptr;
  113. return &devInfo;
  114. }
  115. #ifndef BUILD_BRIDGE
  116. if (index < getRtAudioApiCount())
  117. return getRtAudioDeviceInfo(index, deviceName);
  118. index -= getRtAudioApiCount();
  119. if (index < getJuceApiCount())
  120. return getJuceDeviceInfo(index, deviceName);
  121. #endif
  122. carla_stderr("CarlaEngine::getDriverDeviceNames(%i, \"%s\") - invalid index", index2, deviceName);
  123. return nullptr;
  124. }
  125. CarlaEngine* CarlaEngine::newDriverByName(const char* const driverName)
  126. {
  127. CARLA_SAFE_ASSERT_RETURN(driverName != nullptr && driverName[0] != '\0', nullptr);
  128. carla_debug("CarlaEngine::newDriverByName(\"%s\")", driverName);
  129. if (std::strcmp(driverName, "JACK") == 0)
  130. return newJack();
  131. #ifndef BUILD_BRIDGE
  132. // -------------------------------------------------------------------
  133. // common
  134. if (std::strncmp(driverName, "JACK ", 5) == 0)
  135. return newRtAudio(AUDIO_API_JACK);
  136. // -------------------------------------------------------------------
  137. // linux
  138. if (std::strcmp(driverName, "ALSA") == 0)
  139. //return newJuce(AUDIO_API_ALSA);
  140. return newRtAudio(AUDIO_API_ALSA);
  141. if (std::strcmp(driverName, "OSS") == 0)
  142. return newRtAudio(AUDIO_API_OSS);
  143. if (std::strcmp(driverName, "PulseAudio") == 0)
  144. return newRtAudio(AUDIO_API_PULSE);
  145. // -------------------------------------------------------------------
  146. // macos
  147. if (std::strcmp(driverName, "CoreAudio") == 0)
  148. return newJuce(AUDIO_API_CORE);
  149. // -------------------------------------------------------------------
  150. // windows
  151. if (std::strcmp(driverName, "ASIO") == 0)
  152. return newJuce(AUDIO_API_ASIO);
  153. if (std::strcmp(driverName, "DirectSound") == 0)
  154. return newJuce(AUDIO_API_DS);
  155. #endif
  156. carla_stderr("CarlaEngine::newDriverByName(\"%s\") - invalid driver name", driverName);
  157. return nullptr;
  158. }
  159. // -----------------------------------------------------------------------
  160. // Maximum values
  161. uint CarlaEngine::getMaxClientNameSize() const noexcept
  162. {
  163. return STR_MAX/2;
  164. }
  165. uint CarlaEngine::getMaxPortNameSize() const noexcept
  166. {
  167. return STR_MAX;
  168. }
  169. uint CarlaEngine::getCurrentPluginCount() const noexcept
  170. {
  171. return pData->curPluginCount;
  172. }
  173. uint CarlaEngine::getMaxPluginNumber() const noexcept
  174. {
  175. return pData->maxPluginNumber;
  176. }
  177. // -----------------------------------------------------------------------
  178. // Virtual, per-engine type calls
  179. bool CarlaEngine::init(const char* const clientName)
  180. {
  181. carla_debug("CarlaEngine::init(\"%s\")", clientName);
  182. if (! pData->init(clientName))
  183. return false;
  184. callback(ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, 0.0f, getCurrentDriverName());
  185. return true;
  186. }
  187. bool CarlaEngine::close()
  188. {
  189. carla_debug("CarlaEngine::close()");
  190. if (pData->curPluginCount != 0)
  191. {
  192. pData->aboutToClose = true;
  193. removeAllPlugins();
  194. }
  195. #ifndef BUILD_BRIDGE
  196. if (pData->osc.isControlRegistered())
  197. oscSend_control_exit();
  198. #endif
  199. pData->close();
  200. callback(ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0f, nullptr);
  201. return true;
  202. }
  203. void CarlaEngine::idle() noexcept
  204. {
  205. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,); // TESTING, remove later
  206. CARLA_SAFE_ASSERT_RETURN(pData->nextPluginId == pData->maxPluginNumber,); // TESTING, remove later
  207. CARLA_SAFE_ASSERT_RETURN(pData->plugins != nullptr,); // this one too maybe
  208. for (uint i=0; i < pData->curPluginCount; ++i)
  209. {
  210. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  211. if (plugin != nullptr && plugin->isEnabled())
  212. {
  213. try {
  214. plugin->idle();
  215. } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin idle");
  216. }
  217. }
  218. pData->osc.idle();
  219. }
  220. CarlaEngineClient* CarlaEngine::addClient(CarlaPlugin* const)
  221. {
  222. return new CarlaEngineClient(*this);
  223. }
  224. // -----------------------------------------------------------------------
  225. // Plugin management
  226. bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, const char* const filename, const char* const name, const char* const label, const int64_t uniqueId, const void* const extra)
  227. {
  228. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data (err #10)");
  229. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextPluginId <= pData->maxPluginNumber, "Invalid engine internal data (err #11)");
  230. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data (err #12)");
  231. CARLA_SAFE_ASSERT_RETURN_ERR(btype != BINARY_NONE, "Invalid plugin params (err #1)");
  232. CARLA_SAFE_ASSERT_RETURN_ERR(ptype != PLUGIN_NONE, "Invalid plugin params (err #2)");
  233. CARLA_SAFE_ASSERT_RETURN_ERR((filename != nullptr && filename[0] != '\0') || (label != nullptr && label[0] != '\0'), "Invalid plugin params (err #3)");
  234. carla_debug("CarlaEngine::addPlugin(%i:%s, %i:%s, \"%s\", \"%s\", \"%s\", " P_INT64 ", %p)", btype, BinaryType2Str(btype), ptype, PluginType2Str(ptype), filename, name, label, uniqueId, extra);
  235. uint id;
  236. #ifndef BUILD_BRIDGE
  237. CarlaPlugin* oldPlugin = nullptr;
  238. if (pData->nextPluginId < pData->curPluginCount)
  239. {
  240. id = pData->nextPluginId;
  241. pData->nextPluginId = pData->maxPluginNumber;
  242. oldPlugin = pData->plugins[id].plugin;
  243. CARLA_SAFE_ASSERT_RETURN_ERR(oldPlugin != nullptr, "Invalid replace plugin Id");
  244. }
  245. else
  246. #endif
  247. {
  248. id = pData->curPluginCount;
  249. if (id == pData->maxPluginNumber)
  250. {
  251. setLastError("Maximum number of plugins reached");
  252. return false;
  253. }
  254. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins[id].plugin == nullptr, "Invalid engine internal data (err #13)");
  255. }
  256. CarlaPlugin::Initializer initializer = {
  257. this,
  258. id,
  259. filename,
  260. name,
  261. label,
  262. uniqueId
  263. };
  264. CarlaPlugin* plugin = nullptr;
  265. #ifndef BUILD_BRIDGE
  266. CarlaString bridgeBinary(pData->options.binaryDir);
  267. if (bridgeBinary.isNotEmpty())
  268. {
  269. # ifndef CARLA_OS_WIN
  270. if (btype == BINARY_NATIVE)
  271. {
  272. bridgeBinary += OS_SEP_STR "carla-bridge-native";
  273. }
  274. else
  275. # endif
  276. {
  277. switch (btype)
  278. {
  279. case BINARY_POSIX32:
  280. bridgeBinary += OS_SEP_STR "carla-bridge-posix32";
  281. break;
  282. case BINARY_POSIX64:
  283. bridgeBinary += OS_SEP_STR "carla-bridge-posix64";
  284. break;
  285. case BINARY_WIN32:
  286. bridgeBinary += OS_SEP_STR "carla-bridge-win32.exe";
  287. break;
  288. case BINARY_WIN64:
  289. bridgeBinary += OS_SEP_STR "carla-bridge-win64.exe";
  290. break;
  291. default:
  292. bridgeBinary.clear();
  293. break;
  294. }
  295. }
  296. File file(bridgeBinary.buffer());
  297. if (! file.existsAsFile())
  298. bridgeBinary.clear();
  299. }
  300. if (ptype != PLUGIN_INTERNAL && (btype != BINARY_NATIVE || (pData->options.preferPluginBridges && bridgeBinary.isNotEmpty())))
  301. {
  302. if (bridgeBinary.isNotEmpty())
  303. {
  304. plugin = CarlaPlugin::newBridge(initializer, btype, ptype, bridgeBinary);
  305. }
  306. # ifdef CARLA_OS_LINUX
  307. else if (btype == BINARY_WIN32)
  308. {
  309. // fallback to dssi-vst
  310. File file(filename);
  311. CarlaString label2(file.getFullPathName().toRawUTF8());
  312. label2.replace(' ', '*');
  313. CarlaPlugin::Initializer init2 = {
  314. this,
  315. id,
  316. "/usr/lib/dssi/dssi-vst.so",
  317. name,
  318. label2,
  319. uniqueId
  320. };
  321. char* const oldVstPath(getenv("VST_PATH"));
  322. carla_setenv("VST_PATH", file.getParentDirectory().getFullPathName().toRawUTF8());
  323. plugin = CarlaPlugin::newDSSI(init2);
  324. if (oldVstPath != nullptr)
  325. carla_setenv("VST_PATH", oldVstPath);
  326. }
  327. # endif
  328. else
  329. {
  330. setLastError("This Carla build cannot handle this binary");
  331. return false;
  332. }
  333. }
  334. else
  335. #endif // ! BUILD_BRIDGE
  336. {
  337. bool use16Outs;
  338. setLastError("Invalid or unsupported plugin type");
  339. switch (ptype)
  340. {
  341. case PLUGIN_NONE:
  342. break;
  343. case PLUGIN_INTERNAL:
  344. if (std::strcmp(label, "FluidSynth") == 0)
  345. {
  346. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  347. plugin = CarlaPlugin::newFluidSynth(initializer, use16Outs);
  348. }
  349. else if (std::strcmp(label, "LinuxSampler (GIG)") == 0)
  350. {
  351. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  352. plugin = CarlaPlugin::newLinuxSampler(initializer, "GIG", use16Outs);
  353. }
  354. else if (std::strcmp(label, "LinuxSampler (SF2)") == 0)
  355. {
  356. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  357. plugin = CarlaPlugin::newLinuxSampler(initializer, "SF2", use16Outs);
  358. }
  359. else if (std::strcmp(label, "LinuxSampler (SFZ)") == 0)
  360. {
  361. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  362. plugin = CarlaPlugin::newLinuxSampler(initializer, "SFZ", use16Outs);
  363. }
  364. else
  365. {
  366. plugin = CarlaPlugin::newNative(initializer);
  367. }
  368. break;
  369. case PLUGIN_LADSPA:
  370. plugin = CarlaPlugin::newLADSPA(initializer, (const LADSPA_RDF_Descriptor*)extra);
  371. break;
  372. case PLUGIN_DSSI:
  373. plugin = CarlaPlugin::newDSSI(initializer);
  374. break;
  375. case PLUGIN_LV2:
  376. plugin = CarlaPlugin::newLV2(initializer);
  377. break;
  378. case PLUGIN_VST:
  379. plugin = CarlaPlugin::newVST(initializer);
  380. break;
  381. case PLUGIN_VST3:
  382. plugin = CarlaPlugin::newVST3(initializer);
  383. break;
  384. case PLUGIN_AU:
  385. plugin = CarlaPlugin::newAU(initializer);
  386. break;
  387. case PLUGIN_GIG:
  388. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  389. plugin = CarlaPlugin::newFileGIG(initializer, use16Outs);
  390. break;
  391. case PLUGIN_SF2:
  392. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  393. plugin = CarlaPlugin::newFileSF2(initializer, use16Outs);
  394. break;
  395. case PLUGIN_SFZ:
  396. plugin = CarlaPlugin::newFileSFZ(initializer);
  397. break;
  398. }
  399. }
  400. if (plugin == nullptr)
  401. {
  402. #ifndef BUILD_BRIDGE
  403. pData->plugins[id].plugin = oldPlugin;
  404. #endif
  405. return false;
  406. }
  407. plugin->registerToOscClient();
  408. EnginePluginData& pluginData(pData->plugins[id]);
  409. pluginData.plugin = plugin;
  410. pluginData.insPeak[0] = 0.0f;
  411. pluginData.insPeak[1] = 0.0f;
  412. pluginData.outsPeak[0] = 0.0f;
  413. pluginData.outsPeak[1] = 0.0f;
  414. #ifndef BUILD_BRIDGE
  415. if (oldPlugin != nullptr)
  416. {
  417. bool wasActive = (oldPlugin->getInternalParameterValue(PARAMETER_ACTIVE) >= 0.5f);
  418. float oldDryWet = oldPlugin->getInternalParameterValue(PARAMETER_DRYWET);
  419. float oldVolume = oldPlugin->getInternalParameterValue(PARAMETER_VOLUME);
  420. delete oldPlugin;
  421. callback(ENGINE_CALLBACK_RELOAD_ALL, id, 0, 0, 0.0f, plugin->getName());
  422. if (wasActive)
  423. plugin->setActive(true, true, true);
  424. if (plugin->getHints() & PLUGIN_CAN_DRYWET)
  425. plugin->setDryWet(oldDryWet, true, true);
  426. if (plugin->getHints() & PLUGIN_CAN_VOLUME)
  427. plugin->setVolume(oldVolume, true, true);
  428. }
  429. else
  430. #endif
  431. {
  432. ++pData->curPluginCount;
  433. callback(ENGINE_CALLBACK_PLUGIN_ADDED, id, 0, 0, 0.0f, plugin->getName());
  434. //if (pData->curPluginCount == 1 && pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  435. // callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_DATA_CHANGED, 0, PATCHBAY_ICON_CARLA, 0, 0.0f, nullptr);
  436. }
  437. return true;
  438. }
  439. bool CarlaEngine::addPlugin(const PluginType ptype, const char* const filename, const char* const name, const char* const label, const int64_t uniqueId, const void* const extra)
  440. {
  441. return addPlugin(BINARY_NATIVE, ptype, filename, name, label, uniqueId, extra);
  442. }
  443. bool CarlaEngine::removePlugin(const uint id)
  444. {
  445. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data (err #14)");
  446. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data (err #15)");
  447. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data (err #16)");
  448. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id (err #1)");
  449. carla_debug("CarlaEngine::removePlugin(%i)", id);
  450. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  451. CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to remove");
  452. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data (err #17)");
  453. pData->thread.stopThread(500);
  454. #ifndef BUILD_BRIDGE
  455. const bool lockWait(isRunning() && pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS);
  456. const ScopedActionLock sal(pData, kEnginePostActionRemovePlugin, id, 0, lockWait);
  457. if (isOscControlRegistered())
  458. oscSend_control_remove_plugin(id);
  459. #else
  460. pData->plugins[0].plugin = nullptr;
  461. #endif
  462. delete plugin;
  463. if (isRunning() && ! pData->aboutToClose)
  464. pData->thread.startThread();
  465. callback(ENGINE_CALLBACK_PLUGIN_REMOVED, id, 0, 0, 0.0f, nullptr);
  466. return true;
  467. }
  468. bool CarlaEngine::removeAllPlugins()
  469. {
  470. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data (err #18)");
  471. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextPluginId == pData->maxPluginNumber, "Invalid engine internal data (err #19)");
  472. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data (err #20)");
  473. carla_debug("CarlaEngine::removeAllPlugins()");
  474. if (pData->curPluginCount == 0)
  475. return true;
  476. pData->thread.stopThread(500);
  477. const bool lockWait(isRunning());
  478. const ScopedActionLock sal(pData, kEnginePostActionZeroCount, 0, 0, lockWait);
  479. callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  480. for (uint i=0; i < pData->maxPluginNumber; ++i)
  481. {
  482. EnginePluginData& pluginData(pData->plugins[i]);
  483. if (pluginData.plugin != nullptr)
  484. {
  485. delete pluginData.plugin;
  486. pluginData.plugin = nullptr;
  487. }
  488. pluginData.insPeak[0] = 0.0f;
  489. pluginData.insPeak[1] = 0.0f;
  490. pluginData.outsPeak[0] = 0.0f;
  491. pluginData.outsPeak[1] = 0.0f;
  492. callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  493. }
  494. if (isRunning() && ! pData->aboutToClose)
  495. pData->thread.startThread();
  496. return true;
  497. }
  498. const char* CarlaEngine::renamePlugin(const uint id, const char* const newName)
  499. {
  500. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->plugins != nullptr, "Invalid engine internal data (err #21)");
  501. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->curPluginCount != 0, "Invalid engine internal data (err #22)");
  502. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data (err #23)");
  503. CARLA_SAFE_ASSERT_RETURN_ERRN(id < pData->curPluginCount, "Invalid plugin Id (err #2)");
  504. CARLA_SAFE_ASSERT_RETURN_ERRN(newName != nullptr && newName[0] != '\0', "Invalid plugin name");
  505. carla_debug("CarlaEngine::renamePlugin(%i, \"%s\")", id, newName);
  506. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  507. CARLA_SAFE_ASSERT_RETURN_ERRN(plugin != nullptr, "Could not find plugin to rename");
  508. CARLA_SAFE_ASSERT_RETURN_ERRN(plugin->getId() == id, "Invalid engine internal data (err #24)");
  509. if (const char* const name = getUniquePluginName(newName))
  510. {
  511. plugin->setName(name);
  512. return name;
  513. }
  514. setLastError("Unable to get new unique plugin name");
  515. return nullptr;
  516. }
  517. bool CarlaEngine::clonePlugin(const uint id)
  518. {
  519. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data (err #25)");
  520. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data (err #26)");
  521. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data (err #27)");
  522. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id (err #3)");
  523. carla_debug("CarlaEngine::clonePlugin(%i)", id);
  524. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  525. CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to clone");
  526. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data (err #28)");
  527. char label[STR_MAX+1];
  528. carla_zeroChar(label, STR_MAX+1);
  529. plugin->getLabel(label);
  530. const uint pluginCountBefore(pData->curPluginCount);
  531. if (! addPlugin(plugin->getBinaryType(), plugin->getType(), plugin->getFilename(), plugin->getName(), label, plugin->getUniqueId(), plugin->getExtraStuff()))
  532. return false;
  533. CARLA_SAFE_ASSERT_RETURN_ERR(pluginCountBefore+1 == pData->curPluginCount, "No new plugin found");
  534. if (CarlaPlugin* const newPlugin = pData->plugins[pluginCountBefore].plugin)
  535. newPlugin->loadStateSave(plugin->getStateSave());
  536. return true;
  537. }
  538. bool CarlaEngine::replacePlugin(const uint id)
  539. {
  540. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data (err #29)");
  541. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data (err #30)");
  542. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data (err #31)");
  543. carla_debug("CarlaEngine::replacePlugin(%i)", id);
  544. // might use this to reset
  545. if (id == pData->curPluginCount || id == pData->maxPluginNumber)
  546. {
  547. pData->nextPluginId = pData->maxPluginNumber;
  548. return true;
  549. }
  550. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id (err #4)");
  551. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  552. CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to replace");
  553. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data (err #32)");
  554. pData->nextPluginId = id;
  555. return true;
  556. }
  557. bool CarlaEngine::switchPlugins(const uint idA, const uint idB)
  558. {
  559. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data (err #33)");
  560. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount >= 2, "Invalid engine internal data (err #34)");
  561. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data (err #35)");
  562. CARLA_SAFE_ASSERT_RETURN_ERR(idA != idB, "Invalid operation, cannot switch plugin with itself");
  563. CARLA_SAFE_ASSERT_RETURN_ERR(idA < pData->curPluginCount, "Invalid plugin Id (err #5)");
  564. CARLA_SAFE_ASSERT_RETURN_ERR(idB < pData->curPluginCount, "Invalid plugin Id (err #6)");
  565. carla_debug("CarlaEngine::switchPlugins(%i)", idA, idB);
  566. CarlaPlugin* const pluginA(pData->plugins[idA].plugin);
  567. CarlaPlugin* const pluginB(pData->plugins[idB].plugin);
  568. CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch (err #1)");
  569. CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch (err #2)");
  570. CARLA_SAFE_ASSERT_RETURN_ERR(pluginA->getId() == idA, "Invalid engine internal data (err #36)");
  571. CARLA_SAFE_ASSERT_RETURN_ERR(pluginB->getId() == idB, "Invalid engine internal data (err #37)");
  572. pData->thread.stopThread(500);
  573. #ifndef BUILD_BRIDGE
  574. const bool lockWait(isRunning() && pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS);
  575. const ScopedActionLock sal(pData, kEnginePostActionSwitchPlugins, idA, idB, lockWait);
  576. // TODO
  577. //if (isOscControlRegistered())
  578. // oscSend_control_switch_plugins(idA, idB);
  579. #else
  580. pData->plugins[0].plugin = nullptr;
  581. #endif
  582. if (isRunning() && ! pData->aboutToClose)
  583. pData->thread.startThread();
  584. return true;
  585. }
  586. CarlaPlugin* CarlaEngine::getPlugin(const uint id) const
  587. {
  588. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->plugins != nullptr, "Invalid engine internal data (err #38)");
  589. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->curPluginCount != 0, "Invalid engine internal data (err #39)");
  590. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data (err #40)");
  591. CARLA_SAFE_ASSERT_RETURN_ERRN(id < pData->curPluginCount, "Invalid plugin Id (err #7)");
  592. return pData->plugins[id].plugin;
  593. }
  594. CarlaPlugin* CarlaEngine::getPluginUnchecked(const uint id) const noexcept
  595. {
  596. return pData->plugins[id].plugin;
  597. }
  598. const char* CarlaEngine::getUniquePluginName(const char* const name) const
  599. {
  600. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull, nullptr);
  601. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr);
  602. carla_debug("CarlaEngine::getUniquePluginName(\"%s\")", name);
  603. CarlaString sname;
  604. sname = name;
  605. if (sname.isEmpty())
  606. {
  607. sname = "(No name)";
  608. return sname.dup();
  609. }
  610. const size_t maxNameSize(carla_min<uint>(getMaxClientNameSize(), 0xff, 6) - 6); // 6 = strlen(" (10)") + 1
  611. if (maxNameSize == 0 || ! isRunning())
  612. return sname.dup();
  613. sname.truncate(maxNameSize);
  614. sname.replace(':', '.'); // ':' is used in JACK1 to split client/port names
  615. for (uint i=0; i < pData->curPluginCount; ++i)
  616. {
  617. CARLA_SAFE_ASSERT_BREAK(pData->plugins[i].plugin != nullptr);
  618. // Check if unique name doesn't exist
  619. if (const char* const pluginName = pData->plugins[i].plugin->getName())
  620. {
  621. if (sname != pluginName)
  622. continue;
  623. }
  624. // Check if string has already been modified
  625. {
  626. const size_t len(sname.length());
  627. // 1 digit, ex: " (2)"
  628. if (sname[len-4] == ' ' && sname[len-3] == '(' && sname.isDigit(len-2) && sname[len-1] == ')')
  629. {
  630. int number = sname[len-2] - '0';
  631. if (number == 9)
  632. {
  633. // next number is 10, 2 digits
  634. sname.truncate(len-4);
  635. sname += " (10)";
  636. //sname.replace(" (9)", " (10)");
  637. }
  638. else
  639. sname[len-2] = char('0' + number + 1);
  640. continue;
  641. }
  642. // 2 digits, ex: " (11)"
  643. if (sname[len-5] == ' ' && sname[len-4] == '(' && sname.isDigit(len-3) && sname.isDigit(len-2) && sname[len-1] == ')')
  644. {
  645. char n2 = sname[len-2];
  646. char n3 = sname[len-3];
  647. if (n2 == '9')
  648. {
  649. n2 = '0';
  650. n3 = static_cast<char>(n3 + 1);
  651. }
  652. else
  653. n2 = static_cast<char>(n2 + 1);
  654. sname[len-2] = n2;
  655. sname[len-3] = n3;
  656. continue;
  657. }
  658. }
  659. // Modify string if not
  660. sname += " (2)";
  661. }
  662. return sname.dup();
  663. }
  664. // -----------------------------------------------------------------------
  665. // Project management
  666. bool CarlaEngine::loadFile(const char* const filename)
  667. {
  668. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename (err #1)");
  669. carla_debug("CarlaEngine::loadFile(\"%s\")", filename);
  670. File file(filename);
  671. CARLA_SAFE_ASSERT_RETURN_ERR(file.existsAsFile(), "Requested file does not exist or is not a readable file");
  672. CarlaString baseName(file.getFileName().toRawUTF8());
  673. CarlaString extension(file.getFileExtension().toRawUTF8());
  674. extension.toLower();
  675. // -------------------------------------------------------------------
  676. if (extension == "carxp" || extension == "carxs")
  677. return loadProject(filename);
  678. // -------------------------------------------------------------------
  679. if (extension == "gig")
  680. return addPlugin(PLUGIN_GIG, filename, baseName, baseName, 0, nullptr);
  681. if (extension == "sf2")
  682. return addPlugin(PLUGIN_SF2, filename, baseName, baseName, 0, nullptr);
  683. if (extension == "sfz")
  684. return addPlugin(PLUGIN_SFZ, filename, baseName, baseName, 0, nullptr);
  685. // -------------------------------------------------------------------
  686. if (extension == "aiff" || extension == "flac" || extension == "oga" || extension == "ogg" || extension == "w64" || extension == "wav")
  687. {
  688. #ifdef WANT_AUDIOFILE
  689. if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "audiofile", 0, nullptr))
  690. {
  691. if (CarlaPlugin* const plugin = getPlugin(pData->curPluginCount-1))
  692. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "file", filename, true);
  693. return true;
  694. }
  695. return false;
  696. #else
  697. setLastError("This Carla build does not have Audio file support");
  698. return false;
  699. #endif
  700. }
  701. if (extension == "3g2" || extension == "3gp" || extension == "aac" || extension == "ac3" || extension == "amr" || extension == "ape" ||
  702. extension == "mp2" || extension == "mp3" || extension == "mpc" || extension == "wma")
  703. {
  704. #ifdef WANT_AUDIOFILE
  705. # ifdef HAVE_FFMPEG
  706. if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "audiofile", 0, nullptr))
  707. {
  708. if (CarlaPlugin* const plugin = getPlugin(pData->curPluginCount-1))
  709. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "file", filename, true);
  710. return true;
  711. }
  712. return false;
  713. # else
  714. setLastError("This Carla build has Audio file support, but not libav/ffmpeg");
  715. return false;
  716. # endif
  717. #else
  718. setLastError("This Carla build does not have Audio file support");
  719. return false;
  720. #endif
  721. }
  722. // -------------------------------------------------------------------
  723. if (extension == "mid" || extension == "midi")
  724. {
  725. #ifdef WANT_MIDIFILE
  726. if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "midifile", 0, nullptr))
  727. {
  728. if (CarlaPlugin* const plugin = getPlugin(pData->curPluginCount-1))
  729. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "file", filename, true);
  730. return true;
  731. }
  732. return false;
  733. #else
  734. setLastError("This Carla build does not have MIDI file support");
  735. return false;
  736. #endif
  737. }
  738. // -------------------------------------------------------------------
  739. // ZynAddSubFX
  740. if (extension == "xmz" || extension == "xiz")
  741. {
  742. #ifdef WANT_ZYNADDSUBFX
  743. if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "zynaddsubfx", 0, nullptr))
  744. {
  745. if (CarlaPlugin* const plugin = getPlugin(pData->curPluginCount-1))
  746. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, (extension == "xmz") ? "CarlaAlternateFile1" : "CarlaAlternateFile2", filename, true);
  747. return true;
  748. }
  749. return false;
  750. #else
  751. setLastError("This Carla build does not have ZynAddSubFX support");
  752. return false;
  753. #endif
  754. }
  755. // -------------------------------------------------------------------
  756. setLastError("Unknown file extension");
  757. return false;
  758. }
  759. bool CarlaEngine::loadProject(const char* const filename)
  760. {
  761. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename (err #2)");
  762. carla_debug("CarlaEngine::loadProject(\"%s\")", filename);
  763. File file(filename);
  764. CARLA_SAFE_ASSERT_RETURN_ERR(file.existsAsFile(), "Requested file does not exist or is not a readable file");
  765. XmlDocument xml(file);
  766. ScopedPointer<XmlElement> xmlElement(xml.getDocumentElement(true));
  767. CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to parse project file");
  768. const String& xmlType(xmlElement->getTagName());
  769. const bool isPreset(xmlType.equalsIgnoreCase("carla-preset"));
  770. if (! (xmlType.equalsIgnoreCase("carla-project") || isPreset))
  771. {
  772. setLastError("Not a valid Carla project or preset file");
  773. return false;
  774. }
  775. // completely load file
  776. xmlElement = xml.getDocumentElement(false);
  777. CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to completely parse project file");
  778. // handle plugins first
  779. for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
  780. {
  781. const String& tagName(elem->getTagName());
  782. if (isPreset || tagName.equalsIgnoreCase("plugin"))
  783. {
  784. StateSave stateSave;
  785. stateSave.fillFromXmlElement(isPreset ? xmlElement.get() : elem);
  786. callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  787. CARLA_SAFE_ASSERT_CONTINUE(stateSave.type != nullptr);
  788. const void* extraStuff = nullptr;
  789. // check if using GIG, SF2 or SFZ 16outs
  790. static const char kUse16OutsSuffix[] = " (16 outs)";
  791. const PluginType ptype(getPluginTypeFromString(stateSave.type));
  792. if (CarlaString(stateSave.label).endsWith(kUse16OutsSuffix))
  793. {
  794. if (ptype == PLUGIN_GIG || ptype == PLUGIN_SF2)
  795. extraStuff = "true";
  796. }
  797. // TODO - proper find&load plugins
  798. if (addPlugin(ptype, stateSave.binary, stateSave.name, stateSave.label, stateSave.uniqueId, extraStuff))
  799. {
  800. if (CarlaPlugin* const plugin = getPlugin(pData->curPluginCount-1))
  801. plugin->loadStateSave(stateSave);
  802. }
  803. else
  804. carla_stderr2("Failed to load a plugin, error was:%s\n", getLastError());
  805. }
  806. if (isPreset)
  807. return true;
  808. }
  809. #ifndef BUILD_BRIDGE
  810. callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  811. // if we're running inside some session-manager, let them handle the connections
  812. if (pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY)
  813. {
  814. if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr || std::getenv("LADISH_APP_NAME") != nullptr || std::getenv("NSM_URL") != nullptr)
  815. return true;
  816. }
  817. // now handle connections
  818. for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
  819. {
  820. const String& tagName(elem->getTagName());
  821. if (tagName.equalsIgnoreCase("patchbay"))
  822. {
  823. CarlaString sourcePort, targetPort;
  824. for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement())
  825. {
  826. const String& patchTag(patchElem->getTagName());
  827. sourcePort.clear();
  828. targetPort.clear();
  829. if (! patchTag.equalsIgnoreCase("connection"))
  830. continue;
  831. for (XmlElement* connElem = patchElem->getFirstChildElement(); connElem != nullptr; connElem = connElem->getNextElement())
  832. {
  833. const String& tag(connElem->getTagName());
  834. const String text(connElem->getAllSubText().trim());
  835. if (tag.equalsIgnoreCase("source"))
  836. sourcePort = text.toRawUTF8();
  837. else if (tag.equalsIgnoreCase("target"))
  838. targetPort = text.toRawUTF8();
  839. }
  840. if (sourcePort.isNotEmpty() && targetPort.isNotEmpty())
  841. restorePatchbayConnection(sourcePort, targetPort);
  842. }
  843. break;
  844. }
  845. }
  846. #endif
  847. return true;
  848. }
  849. bool CarlaEngine::saveProject(const char* const filename)
  850. {
  851. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename (err #3)");
  852. carla_debug("CarlaEngine::saveProject(\"%s\")", filename);
  853. MemoryOutputStream out;
  854. out << "<?xml version='1.0' encoding='UTF-8'?>\n";
  855. out << "<!DOCTYPE CARLA-PROJECT>\n";
  856. out << "<CARLA-PROJECT VERSION='2.0'>\n";
  857. bool firstPlugin = true;
  858. char strBuf[STR_MAX+1];
  859. for (uint i=0; i < pData->curPluginCount; ++i)
  860. {
  861. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  862. if (plugin != nullptr && plugin->isEnabled())
  863. {
  864. if (! firstPlugin)
  865. out << "\n";
  866. strBuf[0] = '\0';
  867. plugin->getRealName(strBuf);
  868. //if (strBuf[0] != '\0')
  869. // out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true));
  870. out << " <Plugin>\n";
  871. out << plugin->getStateSave().toString();
  872. out << " </Plugin>\n";
  873. firstPlugin = false;
  874. }
  875. }
  876. #ifndef BUILD_BRIDGE
  877. // if we're running inside some session-manager, let them handle the connections
  878. if (pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY)
  879. {
  880. if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr || std::getenv("LADISH_APP_NAME") != nullptr || std::getenv("NSM_URL") != nullptr)
  881. return true;
  882. }
  883. if (const char* const* patchbayConns = getPatchbayConnections())
  884. {
  885. if (! firstPlugin)
  886. out << "\n";
  887. out << " <Patchbay>\n";
  888. for (int i=0; patchbayConns[i] != nullptr && patchbayConns[i+1] != nullptr; ++i, ++i )
  889. {
  890. const char* const connSource(patchbayConns[i]);
  891. const char* const connTarget(patchbayConns[i+1]);
  892. CARLA_SAFE_ASSERT_CONTINUE(connSource != nullptr && connSource[0] != '\0');
  893. CARLA_SAFE_ASSERT_CONTINUE(connTarget != nullptr && connTarget[0] != '\0');
  894. out << " <Connection>\n";
  895. out << " <Source>" << connSource << "</Source>\n";
  896. out << " <Target>" << connTarget << "</Target>\n";
  897. out << " </Connection>\n";
  898. delete[] connSource;
  899. delete[] connTarget;
  900. }
  901. out << " </Patchbay>\n";
  902. }
  903. #endif
  904. out << "</CARLA-PROJECT>\n";
  905. File file(filename);
  906. if (file.replaceWithData(out.getData(), out.getDataSize()))
  907. return true;
  908. setLastError("Failed to write file");
  909. return false;
  910. }
  911. // -----------------------------------------------------------------------
  912. // Information (base)
  913. uint CarlaEngine::getHints() const noexcept
  914. {
  915. return pData->hints;
  916. }
  917. uint32_t CarlaEngine::getBufferSize() const noexcept
  918. {
  919. return pData->bufferSize;
  920. }
  921. double CarlaEngine::getSampleRate() const noexcept
  922. {
  923. return pData->sampleRate;
  924. }
  925. const char* CarlaEngine::getName() const noexcept
  926. {
  927. return pData->name;
  928. }
  929. EngineProcessMode CarlaEngine::getProccessMode() const noexcept
  930. {
  931. return pData->options.processMode;
  932. }
  933. const EngineOptions& CarlaEngine::getOptions() const noexcept
  934. {
  935. return pData->options;
  936. }
  937. const EngineTimeInfo& CarlaEngine::getTimeInfo() const noexcept
  938. {
  939. return pData->timeInfo;
  940. }
  941. // -----------------------------------------------------------------------
  942. // Information (peaks)
  943. float CarlaEngine::getInputPeak(const uint pluginId, const bool isLeft) const noexcept
  944. {
  945. CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, 0.0f);
  946. return pData->plugins[pluginId].insPeak[isLeft ? 0 : 1];
  947. }
  948. float CarlaEngine::getOutputPeak(const uint pluginId, const bool isLeft) const noexcept
  949. {
  950. CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, 0.0f);
  951. return pData->plugins[pluginId].outsPeak[isLeft ? 0 : 1];
  952. }
  953. // -----------------------------------------------------------------------
  954. // Callback
  955. void CarlaEngine::callback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const float value3, const char* const valueStr) noexcept
  956. {
  957. carla_debug("CarlaEngine::callback(%s, %i, %i, %i, %f, \"%s\")", EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3, valueStr);
  958. if (pData->callback != nullptr)
  959. {
  960. try {
  961. pData->callback(pData->callbackPtr, action, pluginId, value1, value2, value3, valueStr);
  962. } catch(...) {}
  963. }
  964. }
  965. void CarlaEngine::setCallback(const EngineCallbackFunc func, void* const ptr) noexcept
  966. {
  967. carla_debug("CarlaEngine::setCallback(%p, %p)", func, ptr);
  968. pData->callback = func;
  969. pData->callbackPtr = ptr;
  970. }
  971. // -----------------------------------------------------------------------
  972. // File Callback
  973. const char* CarlaEngine::runFileCallback(const FileCallbackOpcode action, const bool isDir, const char* const title, const char* const filter) noexcept
  974. {
  975. CARLA_SAFE_ASSERT_RETURN(title != nullptr && title[0] != '\0', nullptr);
  976. CARLA_SAFE_ASSERT_RETURN(filter != nullptr, nullptr);
  977. carla_debug("CarlaEngine::runFileCallback(%i:%s, %s, \"%s\", \"%s\")", action, FileCallbackOpcode2Str(action), bool2str(isDir), title, filter);
  978. const char* ret = nullptr;
  979. if (pData->fileCallback != nullptr)
  980. {
  981. try {
  982. ret = pData->fileCallback(pData->fileCallbackPtr, action, isDir, title, filter);
  983. } catch(...) {}
  984. }
  985. return ret;
  986. }
  987. void CarlaEngine::setFileCallback(const FileCallbackFunc func, void* const ptr) noexcept
  988. {
  989. carla_debug("CarlaEngine::setFileCallback(%p, %p)", func, ptr);
  990. pData->fileCallback = func;
  991. pData->fileCallbackPtr = ptr;
  992. }
  993. // -----------------------------------------------------------------------
  994. // Transport
  995. void CarlaEngine::transportPlay() noexcept
  996. {
  997. pData->time.playing = true;
  998. }
  999. void CarlaEngine::transportPause() noexcept
  1000. {
  1001. pData->time.playing = false;
  1002. }
  1003. void CarlaEngine::transportRelocate(const uint64_t frame) noexcept
  1004. {
  1005. pData->time.frame = frame;
  1006. }
  1007. // -----------------------------------------------------------------------
  1008. // Error handling
  1009. const char* CarlaEngine::getLastError() const noexcept
  1010. {
  1011. return pData->lastError;
  1012. }
  1013. void CarlaEngine::setLastError(const char* const error) const noexcept
  1014. {
  1015. pData->lastError = error;
  1016. }
  1017. void CarlaEngine::setAboutToClose() noexcept
  1018. {
  1019. carla_debug("CarlaEngine::setAboutToClose()");
  1020. pData->aboutToClose = true;
  1021. }
  1022. // -----------------------------------------------------------------------
  1023. // Global options
  1024. void CarlaEngine::setOption(const EngineOption option, const int value, const char* const valueStr)
  1025. {
  1026. carla_debug("CarlaEngine::setOption(%i:%s, %i, \"%s\")", option, EngineOption2Str(option), value, valueStr);
  1027. if (isRunning() && (option == ENGINE_OPTION_PROCESS_MODE || option == ENGINE_OPTION_AUDIO_NUM_PERIODS || option == ENGINE_OPTION_AUDIO_DEVICE))
  1028. return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Cannot set this option while engine is running!", option, EngineOption2Str(option), value, valueStr);
  1029. switch (option)
  1030. {
  1031. case ENGINE_OPTION_DEBUG:
  1032. case ENGINE_OPTION_NSM_INIT:
  1033. break;
  1034. case ENGINE_OPTION_PROCESS_MODE:
  1035. CARLA_SAFE_ASSERT_RETURN(value >= ENGINE_PROCESS_MODE_SINGLE_CLIENT && value <= ENGINE_PROCESS_MODE_BRIDGE,);
  1036. pData->options.processMode = static_cast<EngineProcessMode>(value);
  1037. break;
  1038. case ENGINE_OPTION_TRANSPORT_MODE:
  1039. CARLA_SAFE_ASSERT_RETURN(value >= ENGINE_TRANSPORT_MODE_INTERNAL && value <= ENGINE_TRANSPORT_MODE_BRIDGE,);
  1040. pData->options.transportMode = static_cast<EngineTransportMode>(value);
  1041. break;
  1042. case ENGINE_OPTION_FORCE_STEREO:
  1043. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1044. pData->options.forceStereo = (value != 0);
  1045. break;
  1046. case ENGINE_OPTION_PREFER_PLUGIN_BRIDGES:
  1047. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1048. pData->options.preferPluginBridges = (value != 0);
  1049. break;
  1050. case ENGINE_OPTION_PREFER_UI_BRIDGES:
  1051. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1052. pData->options.preferUiBridges = (value != 0);
  1053. break;
  1054. case ENGINE_OPTION_UIS_ALWAYS_ON_TOP:
  1055. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1056. pData->options.uisAlwaysOnTop = (value != 0);
  1057. break;
  1058. case ENGINE_OPTION_MAX_PARAMETERS:
  1059. CARLA_SAFE_ASSERT_RETURN(value >= 0,);
  1060. pData->options.maxParameters = static_cast<uint>(value);
  1061. break;
  1062. case ENGINE_OPTION_UI_BRIDGES_TIMEOUT:
  1063. CARLA_SAFE_ASSERT_RETURN(value >= 0,);
  1064. pData->options.uiBridgesTimeout = static_cast<uint>(value);
  1065. break;
  1066. case ENGINE_OPTION_AUDIO_NUM_PERIODS:
  1067. CARLA_SAFE_ASSERT_RETURN(value >= 2 && value <= 3,);
  1068. pData->options.audioNumPeriods = static_cast<uint>(value);
  1069. break;
  1070. case ENGINE_OPTION_AUDIO_BUFFER_SIZE:
  1071. CARLA_SAFE_ASSERT_RETURN(value >= 8,);
  1072. pData->options.audioBufferSize = static_cast<uint>(value);
  1073. break;
  1074. case ENGINE_OPTION_AUDIO_SAMPLE_RATE:
  1075. CARLA_SAFE_ASSERT_RETURN(value >= 22050,);
  1076. pData->options.audioSampleRate = static_cast<uint>(value);
  1077. break;
  1078. case ENGINE_OPTION_AUDIO_DEVICE:
  1079. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,);
  1080. if (pData->options.audioDevice != nullptr)
  1081. delete[] pData->options.audioDevice;
  1082. pData->options.audioDevice = carla_strdup(valueStr);
  1083. break;
  1084. case ENGINE_OPTION_PATH_BINARIES:
  1085. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1086. if (pData->options.binaryDir != nullptr)
  1087. delete[] pData->options.binaryDir;
  1088. pData->options.binaryDir = carla_strdup(valueStr);
  1089. break;
  1090. case ENGINE_OPTION_PATH_RESOURCES:
  1091. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1092. if (pData->options.resourceDir != nullptr)
  1093. delete[] pData->options.resourceDir;
  1094. pData->options.resourceDir = carla_strdup(valueStr);
  1095. break;
  1096. case ENGINE_OPTION_FRONTEND_WIN_ID:
  1097. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1098. const long long winId(std::strtoll(valueStr, nullptr, 16));
  1099. CARLA_SAFE_ASSERT_RETURN(winId >= 0,);
  1100. pData->options.frontendWinId = static_cast<uintptr_t>(winId);
  1101. break;
  1102. }
  1103. }
  1104. // -----------------------------------------------------------------------
  1105. // OSC Stuff
  1106. #ifdef BUILD_BRIDGE
  1107. bool CarlaEngine::isOscBridgeRegistered() const noexcept
  1108. {
  1109. return (pData->oscData != nullptr);
  1110. }
  1111. #else
  1112. bool CarlaEngine::isOscControlRegistered() const noexcept
  1113. {
  1114. return pData->osc.isControlRegistered();
  1115. }
  1116. #endif
  1117. void CarlaEngine::idleOsc() const noexcept
  1118. {
  1119. pData->osc.idle();
  1120. }
  1121. const char* CarlaEngine::getOscServerPathTCP() const noexcept
  1122. {
  1123. return pData->osc.getServerPathTCP();
  1124. }
  1125. const char* CarlaEngine::getOscServerPathUDP() const noexcept
  1126. {
  1127. return pData->osc.getServerPathUDP();
  1128. }
  1129. #ifdef BUILD_BRIDGE
  1130. void CarlaEngine::setOscBridgeData(const CarlaOscData* const oscData) const noexcept
  1131. {
  1132. pData->oscData = oscData;
  1133. }
  1134. #endif
  1135. // -----------------------------------------------------------------------
  1136. // Helper functions
  1137. EngineEvent* CarlaEngine::getInternalEventBuffer(const bool isInput) const noexcept
  1138. {
  1139. return isInput ? pData->events.in : pData->events.out;
  1140. }
  1141. void CarlaEngine::registerEnginePlugin(const uint id, CarlaPlugin* const plugin) noexcept
  1142. {
  1143. CARLA_SAFE_ASSERT_RETURN(id == pData->curPluginCount,);
  1144. carla_debug("CarlaEngine::registerEnginePlugin(%i, %p)", id, plugin);
  1145. pData->plugins[id].plugin = plugin;
  1146. }
  1147. // -----------------------------------------------------------------------
  1148. // Internal stuff
  1149. void CarlaEngine::bufferSizeChanged(const uint32_t newBufferSize)
  1150. {
  1151. carla_debug("CarlaEngine::bufferSizeChanged(%i)", newBufferSize);
  1152. #ifndef BUILD_BRIDGE
  1153. if (pData->graph.graph != nullptr)
  1154. pData->graph.setBufferSize(newBufferSize);
  1155. #endif
  1156. for (uint i=0; i < pData->curPluginCount; ++i)
  1157. {
  1158. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1159. if (plugin != nullptr && plugin->isEnabled())
  1160. plugin->bufferSizeChanged(newBufferSize);
  1161. }
  1162. callback(ENGINE_CALLBACK_BUFFER_SIZE_CHANGED, 0, static_cast<int>(newBufferSize), 0, 0.0f, nullptr);
  1163. }
  1164. void CarlaEngine::sampleRateChanged(const double newSampleRate)
  1165. {
  1166. carla_debug("CarlaEngine::sampleRateChanged(%g)", newSampleRate);
  1167. #ifndef BUILD_BRIDGE
  1168. if (pData->graph.graph != nullptr)
  1169. pData->graph.setSampleRate(newSampleRate);
  1170. #endif
  1171. for (uint i=0; i < pData->curPluginCount; ++i)
  1172. {
  1173. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1174. if (plugin != nullptr && plugin->isEnabled())
  1175. plugin->sampleRateChanged(newSampleRate);
  1176. }
  1177. callback(ENGINE_CALLBACK_SAMPLE_RATE_CHANGED, 0, 0, 0, static_cast<float>(newSampleRate), nullptr);
  1178. }
  1179. void CarlaEngine::offlineModeChanged(const bool isOfflineNow)
  1180. {
  1181. carla_debug("CarlaEngine::offlineModeChanged(%s)", bool2str(isOfflineNow));
  1182. for (uint i=0; i < pData->curPluginCount; ++i)
  1183. {
  1184. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1185. if (plugin != nullptr && plugin->isEnabled())
  1186. plugin->offlineModeChanged(isOfflineNow);
  1187. }
  1188. }
  1189. void CarlaEngine::runPendingRtEvents() noexcept
  1190. {
  1191. pData->doNextPluginAction(true);
  1192. if (pData->time.playing)
  1193. pData->time.frame += pData->bufferSize;
  1194. if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
  1195. {
  1196. pData->timeInfo.playing = pData->time.playing;
  1197. pData->timeInfo.frame = pData->time.frame;
  1198. }
  1199. }
  1200. void CarlaEngine::setPluginPeaks(const uint pluginId, float const inPeaks[2], float const outPeaks[2]) noexcept
  1201. {
  1202. EnginePluginData& pluginData(pData->plugins[pluginId]);
  1203. pluginData.insPeak[0] = inPeaks[0];
  1204. pluginData.insPeak[1] = inPeaks[1];
  1205. pluginData.outsPeak[0] = outPeaks[0];
  1206. pluginData.outsPeak[1] = outPeaks[1];
  1207. }
  1208. // -----------------------------------------------------------------------
  1209. CARLA_BACKEND_END_NAMESPACE