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.

CarlaEngine.cpp 62KB

11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898
  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. */
  24. #include "CarlaEngineInternal.hpp"
  25. #include "CarlaPlugin.hpp"
  26. #include "CarlaBackendUtils.hpp"
  27. #include "CarlaBinaryUtils.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. # if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  63. count += getJuceApiCount();
  64. # else
  65. count += getRtAudioApiCount();
  66. # endif
  67. #endif
  68. return count;
  69. }
  70. const char* CarlaEngine::getDriverName(const uint index2)
  71. {
  72. carla_debug("CarlaEngine::getDriverName(%i)", index2);
  73. uint index(index2);
  74. if (jackbridge_is_ok() && index-- == 0)
  75. return "JACK";
  76. #ifndef BUILD_BRIDGE
  77. # if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  78. if (const uint count = getJuceApiCount())
  79. {
  80. if (index < count)
  81. return getJuceApiName(index);
  82. index -= count;
  83. }
  84. # else
  85. if (const uint count = getRtAudioApiCount())
  86. {
  87. if (index < count)
  88. return getRtAudioApiName(index);
  89. index -= count;
  90. }
  91. # endif
  92. #endif
  93. carla_stderr("CarlaEngine::getDriverName(%i) - invalid index", index2);
  94. return nullptr;
  95. }
  96. const char* const* CarlaEngine::getDriverDeviceNames(const uint index2)
  97. {
  98. carla_debug("CarlaEngine::getDriverDeviceNames(%i)", index2);
  99. uint index(index2);
  100. if (jackbridge_is_ok() && index-- == 0)
  101. {
  102. static const char* ret[3] = { "Auto-Connect OFF", "Auto-Connect ON", nullptr };
  103. return ret;
  104. }
  105. #ifndef BUILD_BRIDGE
  106. # if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  107. if (const uint count = getJuceApiCount())
  108. {
  109. if (index < count)
  110. return getJuceApiDeviceNames(index);
  111. index -= count;
  112. }
  113. # else
  114. if (const uint count = getRtAudioApiCount())
  115. {
  116. if (index < count)
  117. return getRtAudioApiDeviceNames(index);
  118. index -= count;
  119. }
  120. # endif
  121. #endif
  122. carla_stderr("CarlaEngine::getDriverDeviceNames(%i) - invalid index", index2);
  123. return nullptr;
  124. }
  125. const EngineDriverDeviceInfo* CarlaEngine::getDriverDeviceInfo(const uint index2, const char* const deviceName)
  126. {
  127. carla_debug("CarlaEngine::getDriverDeviceInfo(%i, \"%s\")", index2, deviceName);
  128. uint index(index2);
  129. if (jackbridge_is_ok() && index-- == 0)
  130. {
  131. static uint32_t bufSizes[11] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0 };
  132. static EngineDriverDeviceInfo devInfo;
  133. devInfo.hints = ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE;
  134. devInfo.bufferSizes = bufSizes;
  135. devInfo.sampleRates = nullptr;
  136. return &devInfo;
  137. }
  138. #ifndef BUILD_BRIDGE
  139. # if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  140. if (const uint count = getJuceApiCount())
  141. {
  142. if (index < count)
  143. return getJuceDeviceInfo(index, deviceName);
  144. index -= count;
  145. }
  146. # else
  147. if (const uint count = getRtAudioApiCount())
  148. {
  149. if (index < count)
  150. return getRtAudioDeviceInfo(index, deviceName);
  151. index -= count;
  152. }
  153. # endif
  154. #endif
  155. carla_stderr("CarlaEngine::getDriverDeviceNames(%i, \"%s\") - invalid index", index2, deviceName);
  156. return nullptr;
  157. }
  158. CarlaEngine* CarlaEngine::newDriverByName(const char* const driverName)
  159. {
  160. CARLA_SAFE_ASSERT_RETURN(driverName != nullptr && driverName[0] != '\0', nullptr);
  161. carla_debug("CarlaEngine::newDriverByName(\"%s\")", driverName);
  162. if (std::strcmp(driverName, "JACK") == 0)
  163. return newJack();
  164. #ifndef BUILD_BRIDGE
  165. # if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  166. // -------------------------------------------------------------------
  167. // macos
  168. if (std::strcmp(driverName, "CoreAudio") == 0)
  169. return newJuce(AUDIO_API_CORE);
  170. // -------------------------------------------------------------------
  171. // windows
  172. if (std::strcmp(driverName, "ASIO") == 0)
  173. return newJuce(AUDIO_API_ASIO);
  174. if (std::strcmp(driverName, "DirectSound") == 0)
  175. return newJuce(AUDIO_API_DS);
  176. #else
  177. // -------------------------------------------------------------------
  178. // common
  179. if (std::strncmp(driverName, "JACK ", 5) == 0)
  180. return newRtAudio(AUDIO_API_JACK);
  181. // -------------------------------------------------------------------
  182. // linux
  183. if (std::strcmp(driverName, "ALSA") == 0)
  184. return newRtAudio(AUDIO_API_ALSA);
  185. if (std::strcmp(driverName, "OSS") == 0)
  186. return newRtAudio(AUDIO_API_OSS);
  187. if (std::strcmp(driverName, "PulseAudio") == 0)
  188. return newRtAudio(AUDIO_API_PULSE);
  189. # endif
  190. #endif
  191. carla_stderr("CarlaEngine::newDriverByName(\"%s\") - invalid driver name", driverName);
  192. return nullptr;
  193. }
  194. // -----------------------------------------------------------------------
  195. // Constant values
  196. uint CarlaEngine::getMaxClientNameSize() const noexcept
  197. {
  198. return STR_MAX/2;
  199. }
  200. uint CarlaEngine::getMaxPortNameSize() const noexcept
  201. {
  202. return STR_MAX;
  203. }
  204. uint CarlaEngine::getCurrentPluginCount() const noexcept
  205. {
  206. return pData->curPluginCount;
  207. }
  208. uint CarlaEngine::getMaxPluginNumber() const noexcept
  209. {
  210. return pData->maxPluginNumber;
  211. }
  212. // -----------------------------------------------------------------------
  213. // Virtual, per-engine type calls
  214. bool CarlaEngine::close()
  215. {
  216. carla_debug("CarlaEngine::close()");
  217. if (pData->curPluginCount != 0)
  218. {
  219. pData->aboutToClose = true;
  220. removeAllPlugins();
  221. }
  222. #ifndef BUILD_BRIDGE
  223. if (pData->osc.isControlRegistered())
  224. oscSend_control_exit();
  225. #endif
  226. pData->close();
  227. callback(ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0f, nullptr);
  228. return true;
  229. }
  230. void CarlaEngine::idle() noexcept
  231. {
  232. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,); // FIXME REMOVE
  233. CARLA_SAFE_ASSERT_RETURN(pData->nextPluginId == pData->maxPluginNumber,);
  234. for (uint i=0; i < pData->curPluginCount; ++i)
  235. {
  236. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  237. if (plugin != nullptr && plugin->isEnabled())
  238. {
  239. try {
  240. plugin->idle();
  241. } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin idle");
  242. }
  243. }
  244. pData->osc.idle();
  245. }
  246. CarlaEngineClient* CarlaEngine::addClient(CarlaPlugin* const)
  247. {
  248. return new CarlaEngineClient(*this);
  249. }
  250. // -----------------------------------------------------------------------
  251. // Plugin management
  252. 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)
  253. {
  254. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  255. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  256. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextPluginId <= pData->maxPluginNumber, "Invalid engine internal data");
  257. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  258. CARLA_SAFE_ASSERT_RETURN_ERR(btype != BINARY_NONE, "Invalid plugin binary mode");
  259. CARLA_SAFE_ASSERT_RETURN_ERR(ptype != PLUGIN_NONE, "Invalid plugin type");
  260. CARLA_SAFE_ASSERT_RETURN_ERR((filename != nullptr && filename[0] != '\0') || (label != nullptr && label[0] != '\0'), "Invalid plugin filename and label");
  261. 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);
  262. uint id;
  263. #ifndef BUILD_BRIDGE
  264. CarlaPlugin* oldPlugin = nullptr;
  265. if (pData->nextPluginId < pData->curPluginCount)
  266. {
  267. id = pData->nextPluginId;
  268. pData->nextPluginId = pData->maxPluginNumber;
  269. oldPlugin = pData->plugins[id].plugin;
  270. CARLA_SAFE_ASSERT_RETURN_ERR(oldPlugin != nullptr, "Invalid replace plugin Id");
  271. }
  272. else
  273. #endif
  274. {
  275. id = pData->curPluginCount;
  276. if (id == pData->maxPluginNumber)
  277. {
  278. setLastError("Maximum number of plugins reached");
  279. return false;
  280. }
  281. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins[id].plugin == nullptr, "Invalid engine internal data");
  282. }
  283. CarlaPlugin::Initializer initializer = {
  284. this,
  285. id,
  286. filename,
  287. name,
  288. label,
  289. uniqueId
  290. };
  291. CarlaPlugin* plugin = nullptr;
  292. #ifndef BUILD_BRIDGE
  293. CarlaString bridgeBinary(pData->options.binaryDir);
  294. if (bridgeBinary.isNotEmpty())
  295. {
  296. # ifndef CARLA_OS_WIN
  297. if (btype == BINARY_NATIVE)
  298. {
  299. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-native";
  300. }
  301. else
  302. # endif
  303. {
  304. switch (btype)
  305. {
  306. case BINARY_POSIX32:
  307. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-posix32";
  308. break;
  309. case BINARY_POSIX64:
  310. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-posix64";
  311. break;
  312. case BINARY_WIN32:
  313. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-win32.exe";
  314. break;
  315. case BINARY_WIN64:
  316. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-win64.exe";
  317. break;
  318. default:
  319. bridgeBinary.clear();
  320. break;
  321. }
  322. }
  323. if (! File(bridgeBinary.buffer()).existsAsFile())
  324. bridgeBinary.clear();
  325. }
  326. if (ptype != PLUGIN_INTERNAL && (btype != BINARY_NATIVE || (pData->options.preferPluginBridges && bridgeBinary.isNotEmpty())))
  327. {
  328. if (bridgeBinary.isNotEmpty())
  329. {
  330. plugin = CarlaPlugin::newBridge(initializer, btype, ptype, bridgeBinary);
  331. }
  332. # ifdef CARLA_OS_LINUX
  333. // fallback to dssi-vst if possible
  334. else if (btype == BINARY_WIN32 && File("/usr/lib/dssi/dssi-vst.so").existsAsFile())
  335. {
  336. File file(filename);
  337. CarlaString label2(file.getFileName().toRawUTF8());
  338. label2.replace(' ', '*');
  339. CarlaPlugin::Initializer init2 = {
  340. this,
  341. id,
  342. "/usr/lib/dssi/dssi-vst.so",
  343. name,
  344. label2,
  345. uniqueId
  346. };
  347. char* const oldVstPath(std::getenv("VST_PATH"));
  348. carla_setenv("VST_PATH", file.getParentDirectory().getFullPathName().toRawUTF8());
  349. plugin = CarlaPlugin::newDSSI(init2);
  350. if (oldVstPath != nullptr)
  351. carla_setenv("VST_PATH", oldVstPath);
  352. }
  353. # endif
  354. else
  355. {
  356. setLastError("This Carla build cannot handle this binary");
  357. return false;
  358. }
  359. }
  360. else
  361. #endif // ! BUILD_BRIDGE
  362. {
  363. bool use16Outs;
  364. setLastError("Invalid or unsupported plugin type");
  365. switch (ptype)
  366. {
  367. case PLUGIN_NONE:
  368. break;
  369. case PLUGIN_INTERNAL:
  370. /*if (std::strcmp(label, "FluidSynth") == 0)
  371. {
  372. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  373. plugin = CarlaPlugin::newFluidSynth(initializer, use16Outs);
  374. }
  375. else if (std::strcmp(label, "LinuxSampler (GIG)") == 0)
  376. {
  377. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  378. plugin = CarlaPlugin::newLinuxSampler(initializer, "GIG", use16Outs);
  379. }
  380. else if (std::strcmp(label, "LinuxSampler (SF2)") == 0)
  381. {
  382. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  383. plugin = CarlaPlugin::newLinuxSampler(initializer, "SF2", use16Outs);
  384. }
  385. else if (std::strcmp(label, "LinuxSampler (SFZ)") == 0)
  386. {
  387. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  388. plugin = CarlaPlugin::newLinuxSampler(initializer, "SFZ", use16Outs);
  389. }*/
  390. plugin = CarlaPlugin::newNative(initializer);
  391. break;
  392. case PLUGIN_LADSPA:
  393. plugin = CarlaPlugin::newLADSPA(initializer, (const LADSPA_RDF_Descriptor*)extra);
  394. break;
  395. case PLUGIN_DSSI:
  396. plugin = CarlaPlugin::newDSSI(initializer);
  397. break;
  398. case PLUGIN_LV2:
  399. plugin = CarlaPlugin::newLV2(initializer);
  400. break;
  401. case PLUGIN_VST:
  402. plugin = CarlaPlugin::newVST(initializer);
  403. break;
  404. case PLUGIN_VST3:
  405. plugin = CarlaPlugin::newVST3(initializer);
  406. break;
  407. case PLUGIN_AU:
  408. plugin = CarlaPlugin::newAU(initializer);
  409. break;
  410. case PLUGIN_GIG:
  411. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  412. plugin = CarlaPlugin::newFileGIG(initializer, use16Outs);
  413. break;
  414. case PLUGIN_SF2:
  415. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  416. plugin = CarlaPlugin::newFileSF2(initializer, use16Outs);
  417. break;
  418. case PLUGIN_SFZ:
  419. plugin = CarlaPlugin::newFileSFZ(initializer);
  420. break;
  421. }
  422. }
  423. if (plugin == nullptr)
  424. return false;
  425. plugin->registerToOscClient();
  426. EnginePluginData& pluginData(pData->plugins[id]);
  427. pluginData.plugin = plugin;
  428. pluginData.insPeak[0] = 0.0f;
  429. pluginData.insPeak[1] = 0.0f;
  430. pluginData.outsPeak[0] = 0.0f;
  431. pluginData.outsPeak[1] = 0.0f;
  432. #ifndef BUILD_BRIDGE
  433. if (oldPlugin != nullptr)
  434. {
  435. // the engine thread might be reading from the old plugin
  436. pData->thread.stopThread(500);
  437. pData->thread.startThread();
  438. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  439. pData->graph.replacePlugin(oldPlugin, plugin);
  440. const bool wasActive = oldPlugin->getInternalParameterValue(PARAMETER_ACTIVE) >= 0.5f;
  441. const float oldDryWet = oldPlugin->getInternalParameterValue(PARAMETER_DRYWET);
  442. const float oldVolume = oldPlugin->getInternalParameterValue(PARAMETER_VOLUME);
  443. delete oldPlugin;
  444. if (plugin->getHints() & PLUGIN_CAN_DRYWET)
  445. plugin->setDryWet(oldDryWet, true, true);
  446. if (plugin->getHints() & PLUGIN_CAN_VOLUME)
  447. plugin->setVolume(oldVolume, true, true);
  448. if (wasActive)
  449. plugin->setActive(true, true, true);
  450. callback(ENGINE_CALLBACK_RELOAD_ALL, id, 0, 0, 0.0f, nullptr);
  451. }
  452. else
  453. #endif
  454. {
  455. ++pData->curPluginCount;
  456. callback(ENGINE_CALLBACK_PLUGIN_ADDED, id, 0, 0, 0.0f, plugin->getName());
  457. #ifndef BUILD_BRIDGE
  458. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  459. pData->graph.addPlugin(plugin);
  460. #endif
  461. }
  462. return true;
  463. }
  464. 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)
  465. {
  466. return addPlugin(BINARY_NATIVE, ptype, filename, name, label, uniqueId, extra);
  467. }
  468. bool CarlaEngine::removePlugin(const uint id)
  469. {
  470. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  471. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  472. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data");
  473. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  474. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id");
  475. carla_debug("CarlaEngine::removePlugin(%i)", id);
  476. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  477. CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to remove");
  478. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data");
  479. pData->thread.stopThread(500);
  480. #ifndef BUILD_BRIDGE
  481. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  482. pData->graph.removePlugin(plugin);
  483. const bool lockWait(isRunning() /*&& pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS*/);
  484. const ScopedActionLock sal(pData, kEnginePostActionRemovePlugin, id, 0, lockWait);
  485. for (uint i=id; i < pData->curPluginCount; ++i)
  486. {
  487. CarlaPlugin* const plugin2(pData->plugins[i].plugin);
  488. CARLA_SAFE_ASSERT_BREAK(plugin2 != nullptr);
  489. plugin2->updateOscURL();
  490. }
  491. if (isOscControlRegistered())
  492. oscSend_control_remove_plugin(id);
  493. #else
  494. pData->curPluginCount = 0;
  495. carla_zeroStruct(pData->plugins, 1);
  496. #endif
  497. delete plugin;
  498. if (isRunning() && ! pData->aboutToClose)
  499. pData->thread.startThread();
  500. callback(ENGINE_CALLBACK_PLUGIN_REMOVED, id, 0, 0, 0.0f, nullptr);
  501. return true;
  502. }
  503. bool CarlaEngine::removeAllPlugins()
  504. {
  505. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  506. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  507. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextPluginId == pData->maxPluginNumber, "Invalid engine internal data");
  508. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  509. carla_debug("CarlaEngine::removeAllPlugins()");
  510. if (pData->curPluginCount == 0)
  511. return true;
  512. pData->thread.stopThread(500);
  513. #ifndef BUILD_BRIDGE
  514. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  515. pData->graph.removeAllPlugins(this);
  516. #endif
  517. const uint32_t curPluginCount(pData->curPluginCount);
  518. const bool lockWait(isRunning());
  519. const ScopedActionLock sal(pData, kEnginePostActionZeroCount, 0, 0, lockWait);
  520. callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  521. for (uint i=0; i < curPluginCount; ++i)
  522. {
  523. EnginePluginData& pluginData(pData->plugins[i]);
  524. if (pluginData.plugin != nullptr)
  525. {
  526. delete pluginData.plugin;
  527. pluginData.plugin = nullptr;
  528. }
  529. pluginData.insPeak[0] = 0.0f;
  530. pluginData.insPeak[1] = 0.0f;
  531. pluginData.outsPeak[0] = 0.0f;
  532. pluginData.outsPeak[1] = 0.0f;
  533. callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  534. }
  535. if (isRunning() && ! pData->aboutToClose)
  536. pData->thread.startThread();
  537. return true;
  538. }
  539. #ifndef BUILD_BRIDGE
  540. const char* CarlaEngine::renamePlugin(const uint id, const char* const newName)
  541. {
  542. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  543. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->plugins != nullptr, "Invalid engine internal data");
  544. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->curPluginCount != 0, "Invalid engine internal data");
  545. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  546. CARLA_SAFE_ASSERT_RETURN_ERRN(id < pData->curPluginCount, "Invalid plugin Id");
  547. CARLA_SAFE_ASSERT_RETURN_ERRN(newName != nullptr && newName[0] != '\0', "Invalid plugin name");
  548. carla_debug("CarlaEngine::renamePlugin(%i, \"%s\")", id, newName);
  549. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  550. CARLA_SAFE_ASSERT_RETURN_ERRN(plugin != nullptr, "Could not find plugin to rename");
  551. CARLA_SAFE_ASSERT_RETURN_ERRN(plugin->getId() == id, "Invalid engine internal data");
  552. if (const char* const name = getUniquePluginName(newName))
  553. {
  554. plugin->setName(name);
  555. return name;
  556. }
  557. setLastError("Unable to get new unique plugin name");
  558. return nullptr;
  559. }
  560. bool CarlaEngine::clonePlugin(const uint id)
  561. {
  562. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  563. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  564. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data");
  565. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  566. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id");
  567. carla_debug("CarlaEngine::clonePlugin(%i)", id);
  568. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  569. CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to clone");
  570. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data");
  571. char label[STR_MAX+1];
  572. carla_zeroChar(label, STR_MAX+1);
  573. plugin->getLabel(label);
  574. const uint pluginCountBefore(pData->curPluginCount);
  575. if (! addPlugin(plugin->getBinaryType(), plugin->getType(), plugin->getFilename(), plugin->getName(), label, plugin->getUniqueId(), plugin->getExtraStuff()))
  576. return false;
  577. CARLA_SAFE_ASSERT_RETURN_ERR(pluginCountBefore+1 == pData->curPluginCount, "No new plugin found");
  578. if (CarlaPlugin* const newPlugin = pData->plugins[pluginCountBefore].plugin)
  579. newPlugin->loadStateSave(plugin->getStateSave());
  580. return true;
  581. }
  582. bool CarlaEngine::replacePlugin(const uint id) noexcept
  583. {
  584. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  585. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  586. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data");
  587. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  588. carla_debug("CarlaEngine::replacePlugin(%i)", id);
  589. // might use this to reset
  590. if (id == pData->maxPluginNumber)
  591. {
  592. pData->nextPluginId = pData->maxPluginNumber;
  593. return true;
  594. }
  595. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id");
  596. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  597. CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to replace");
  598. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data");
  599. pData->nextPluginId = id;
  600. return true;
  601. }
  602. bool CarlaEngine::switchPlugins(const uint idA, const uint idB) noexcept
  603. {
  604. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  605. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  606. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount >= 2, "Invalid engine internal data");
  607. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  608. CARLA_SAFE_ASSERT_RETURN_ERR(idA != idB, "Invalid operation, cannot switch plugin with itself");
  609. CARLA_SAFE_ASSERT_RETURN_ERR(idA < pData->curPluginCount, "Invalid plugin Id");
  610. CARLA_SAFE_ASSERT_RETURN_ERR(idB < pData->curPluginCount, "Invalid plugin Id");
  611. carla_debug("CarlaEngine::switchPlugins(%i)", idA, idB);
  612. {
  613. CarlaPlugin* const pluginA(pData->plugins[idA].plugin);
  614. CarlaPlugin* const pluginB(pData->plugins[idB].plugin);
  615. CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch");
  616. CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch");
  617. CARLA_SAFE_ASSERT_RETURN_ERR(pluginA->getId() == idA, "Invalid engine internal data");
  618. CARLA_SAFE_ASSERT_RETURN_ERR(pluginB->getId() == idB, "Invalid engine internal data");
  619. pData->thread.stopThread(500);
  620. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  621. pData->graph.replacePlugin(pluginA, pluginB);
  622. }
  623. const bool lockWait(isRunning() /*&& pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS*/);
  624. const ScopedActionLock sal(pData, kEnginePostActionSwitchPlugins, idA, idB, lockWait);
  625. CarlaPlugin* const pluginA(pData->plugins[idA].plugin);
  626. CarlaPlugin* const pluginB(pData->plugins[idB].plugin);
  627. if (pluginA != nullptr && pluginB != nullptr)
  628. {
  629. pluginA->updateOscURL();
  630. pluginB->updateOscURL();
  631. }
  632. // TODO
  633. //if (isOscControlRegistered())
  634. // oscSend_control_switch_plugins(idA, idB);
  635. if (isRunning() && ! pData->aboutToClose)
  636. pData->thread.startThread();
  637. return true;
  638. }
  639. #endif
  640. CarlaPlugin* CarlaEngine::getPlugin(const uint id) const noexcept
  641. {
  642. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->plugins != nullptr, "Invalid engine internal data");
  643. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->curPluginCount != 0, "Invalid engine internal data");
  644. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  645. CARLA_SAFE_ASSERT_RETURN_ERRN(id < pData->curPluginCount, "Invalid plugin Id");
  646. return pData->plugins[id].plugin;
  647. }
  648. CarlaPlugin* CarlaEngine::getPluginUnchecked(const uint id) const noexcept
  649. {
  650. return pData->plugins[id].plugin;
  651. }
  652. const char* CarlaEngine::getUniquePluginName(const char* const name) const
  653. {
  654. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull, nullptr);
  655. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr);
  656. carla_debug("CarlaEngine::getUniquePluginName(\"%s\")", name);
  657. CarlaString sname;
  658. sname = name;
  659. if (sname.isEmpty())
  660. {
  661. sname = "(No name)";
  662. return sname.dup();
  663. }
  664. const size_t maxNameSize(carla_min<uint>(getMaxClientNameSize(), 0xff, 6) - 6); // 6 = strlen(" (10)") + 1
  665. if (maxNameSize == 0 || ! isRunning())
  666. return sname.dup();
  667. sname.truncate(maxNameSize);
  668. sname.replace(':', '.'); // ':' is used in JACK1 to split client/port names
  669. for (uint i=0; i < pData->curPluginCount; ++i)
  670. {
  671. CARLA_SAFE_ASSERT_BREAK(pData->plugins[i].plugin != nullptr);
  672. // Check if unique name doesn't exist
  673. if (const char* const pluginName = pData->plugins[i].plugin->getName())
  674. {
  675. if (sname != pluginName)
  676. continue;
  677. }
  678. // Check if string has already been modified
  679. {
  680. const size_t len(sname.length());
  681. // 1 digit, ex: " (2)"
  682. if (sname[len-4] == ' ' && sname[len-3] == '(' && sname.isDigit(len-2) && sname[len-1] == ')')
  683. {
  684. int number = sname[len-2] - '0';
  685. if (number == 9)
  686. {
  687. // next number is 10, 2 digits
  688. sname.truncate(len-4);
  689. sname += " (10)";
  690. //sname.replace(" (9)", " (10)");
  691. }
  692. else
  693. sname[len-2] = char('0' + number + 1);
  694. continue;
  695. }
  696. // 2 digits, ex: " (11)"
  697. if (sname[len-5] == ' ' && sname[len-4] == '(' && sname.isDigit(len-3) && sname.isDigit(len-2) && sname[len-1] == ')')
  698. {
  699. char n2 = sname[len-2];
  700. char n3 = sname[len-3];
  701. if (n2 == '9')
  702. {
  703. n2 = '0';
  704. n3 = static_cast<char>(n3 + 1);
  705. }
  706. else
  707. n2 = static_cast<char>(n2 + 1);
  708. sname[len-2] = n2;
  709. sname[len-3] = n3;
  710. continue;
  711. }
  712. }
  713. // Modify string if not
  714. sname += " (2)";
  715. }
  716. return sname.dup();
  717. }
  718. // -----------------------------------------------------------------------
  719. // Project management
  720. bool CarlaEngine::loadFile(const char* const filename)
  721. {
  722. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  723. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename");
  724. carla_debug("CarlaEngine::loadFile(\"%s\")", filename);
  725. File file(filename);
  726. CARLA_SAFE_ASSERT_RETURN_ERR(file.existsAsFile(), "Requested file does not exist or is not a readable file");
  727. CarlaString baseName(file.getFileName().toRawUTF8());
  728. CarlaString extension(file.getFileExtension().replace(".","").toLowerCase().toRawUTF8());
  729. // -------------------------------------------------------------------
  730. if (extension == "carxp" || extension == "carxs")
  731. return loadProject(filename);
  732. // -------------------------------------------------------------------
  733. if (extension == "gig")
  734. return addPlugin(PLUGIN_GIG, filename, baseName, baseName, 0, nullptr);
  735. if (extension == "sf2")
  736. return addPlugin(PLUGIN_SF2, filename, baseName, baseName, 0, nullptr);
  737. if (extension == "sfz")
  738. return addPlugin(PLUGIN_SFZ, filename, baseName, baseName, 0, nullptr);
  739. // -------------------------------------------------------------------
  740. if (extension == "aif" || extension == "aiff" || extension == "bwf" || extension == "flac" || extension == "ogg" || extension == "wav")
  741. {
  742. if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "audiofile", 0, nullptr))
  743. {
  744. if (CarlaPlugin* const plugin = getPlugin(pData->curPluginCount-1))
  745. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "file", filename, true);
  746. return true;
  747. }
  748. return false;
  749. }
  750. // -------------------------------------------------------------------
  751. if (extension == "mid" || extension == "midi")
  752. {
  753. if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "midifile", 0, nullptr))
  754. {
  755. if (CarlaPlugin* const plugin = getPlugin(pData->curPluginCount-1))
  756. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "file", filename, true);
  757. return true;
  758. }
  759. return false;
  760. }
  761. // -------------------------------------------------------------------
  762. // ZynAddSubFX
  763. if (extension == "xmz" || extension == "xiz")
  764. {
  765. #ifdef WANT_ZYNADDSUBFX
  766. if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "zynaddsubfx", 0, nullptr))
  767. {
  768. if (CarlaPlugin* const plugin = getPlugin(pData->curPluginCount-1))
  769. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, (extension == "xmz") ? "CarlaAlternateFile1" : "CarlaAlternateFile2", filename, true);
  770. return true;
  771. }
  772. return false;
  773. #else
  774. setLastError("This Carla build does not have ZynAddSubFX support");
  775. return false;
  776. #endif
  777. }
  778. // -------------------------------------------------------------------
  779. setLastError("Unknown file extension");
  780. return false;
  781. }
  782. bool CarlaEngine::loadProject(const char* const filename)
  783. {
  784. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  785. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename");
  786. carla_debug("CarlaEngine::loadProject(\"%s\")", filename);
  787. File file(filename);
  788. CARLA_SAFE_ASSERT_RETURN_ERR(file.existsAsFile(), "Requested file does not exist or is not a readable file");
  789. XmlDocument xml(file);
  790. return loadProjectInternal(xml);
  791. }
  792. bool CarlaEngine::saveProject(const char* const filename)
  793. {
  794. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename");
  795. carla_debug("CarlaEngine::saveProject(\"%s\")", filename);
  796. MemoryOutputStream out;
  797. saveProjectInternal(out);
  798. File file(filename);
  799. if (file.replaceWithData(out.getData(), out.getDataSize()))
  800. return true;
  801. setLastError("Failed to write file");
  802. return false;
  803. }
  804. // -----------------------------------------------------------------------
  805. // Information (base)
  806. uint CarlaEngine::getHints() const noexcept
  807. {
  808. return pData->hints;
  809. }
  810. uint32_t CarlaEngine::getBufferSize() const noexcept
  811. {
  812. return pData->bufferSize;
  813. }
  814. double CarlaEngine::getSampleRate() const noexcept
  815. {
  816. return pData->sampleRate;
  817. }
  818. const char* CarlaEngine::getName() const noexcept
  819. {
  820. return pData->name;
  821. }
  822. EngineProcessMode CarlaEngine::getProccessMode() const noexcept
  823. {
  824. return pData->options.processMode;
  825. }
  826. const EngineOptions& CarlaEngine::getOptions() const noexcept
  827. {
  828. return pData->options;
  829. }
  830. const EngineTimeInfo& CarlaEngine::getTimeInfo() const noexcept
  831. {
  832. return pData->timeInfo;
  833. }
  834. // -----------------------------------------------------------------------
  835. // Information (peaks)
  836. float CarlaEngine::getInputPeak(const uint pluginId, const bool isLeft) const noexcept
  837. {
  838. CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, 0.0f);
  839. return pData->plugins[pluginId].insPeak[isLeft ? 0 : 1];
  840. }
  841. float CarlaEngine::getOutputPeak(const uint pluginId, const bool isLeft) const noexcept
  842. {
  843. CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, 0.0f);
  844. return pData->plugins[pluginId].outsPeak[isLeft ? 0 : 1];
  845. }
  846. // -----------------------------------------------------------------------
  847. // Callback
  848. void CarlaEngine::callback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const float value3, const char* const valueStr) noexcept
  849. {
  850. carla_debug("CarlaEngine::callback(%i:%s, %i, %i, %i, %f, \"%s\")", action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3, valueStr);
  851. #ifdef BUILD_BRIDGE
  852. if (pData->isIdling)
  853. #else
  854. if (pData->isIdling && action != ENGINE_CALLBACK_PATCHBAY_CLIENT_DATA_CHANGED)
  855. #endif
  856. {
  857. carla_stdout("callback while idling (%i:%s, %i, %i, %i, %f, \"%s\")", action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3, valueStr);
  858. }
  859. if (action == ENGINE_CALLBACK_IDLE)
  860. {
  861. ++pData->isIdling;
  862. }
  863. #ifdef BUILD_BRIDGE
  864. else if (pData->oscData != nullptr)
  865. {
  866. switch (action)
  867. {
  868. case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED:
  869. CARLA_SAFE_ASSERT_BREAK(value1 >= 0);
  870. oscSend_bridge_parameter_value(static_cast<uint>(value1), value3);
  871. break;
  872. case ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED:
  873. CARLA_SAFE_ASSERT_BREAK(value1 >= 0);
  874. oscSend_bridge_default_value(static_cast<uint>(value1), value3);
  875. break;
  876. case ENGINE_CALLBACK_PROGRAM_CHANGED:
  877. CARLA_SAFE_ASSERT_BREAK(value1 >= -1);
  878. oscSend_bridge_current_program(value1);
  879. break;
  880. case ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED:
  881. CARLA_SAFE_ASSERT_BREAK(value1 >= -1);
  882. oscSend_bridge_current_midi_program(value1);
  883. break;
  884. case ENGINE_CALLBACK_UI_STATE_CHANGED:
  885. if (value1 != 1)
  886. oscSend_bridge_configure("CarlaBridgeHideGUI", "");
  887. break;
  888. default:
  889. break;
  890. }
  891. }
  892. #endif
  893. if (pData->callback != nullptr)
  894. {
  895. try {
  896. pData->callback(pData->callbackPtr, action, pluginId, value1, value2, value3, valueStr);
  897. } CARLA_SAFE_EXCEPTION("callback");
  898. }
  899. if (action == ENGINE_CALLBACK_IDLE)
  900. --pData->isIdling;
  901. }
  902. void CarlaEngine::setCallback(const EngineCallbackFunc func, void* const ptr) noexcept
  903. {
  904. carla_debug("CarlaEngine::setCallback(%p, %p)", func, ptr);
  905. pData->callback = func;
  906. pData->callbackPtr = ptr;
  907. }
  908. // -----------------------------------------------------------------------
  909. // File Callback
  910. const char* CarlaEngine::runFileCallback(const FileCallbackOpcode action, const bool isDir, const char* const title, const char* const filter) noexcept
  911. {
  912. CARLA_SAFE_ASSERT_RETURN(title != nullptr && title[0] != '\0', nullptr);
  913. CARLA_SAFE_ASSERT_RETURN(filter != nullptr, nullptr);
  914. carla_debug("CarlaEngine::runFileCallback(%i:%s, %s, \"%s\", \"%s\")", action, FileCallbackOpcode2Str(action), bool2str(isDir), title, filter);
  915. const char* ret = nullptr;
  916. if (pData->fileCallback != nullptr)
  917. {
  918. try {
  919. ret = pData->fileCallback(pData->fileCallbackPtr, action, isDir, title, filter);
  920. } CARLA_SAFE_EXCEPTION("runFileCallback");
  921. }
  922. return ret;
  923. }
  924. void CarlaEngine::setFileCallback(const FileCallbackFunc func, void* const ptr) noexcept
  925. {
  926. carla_debug("CarlaEngine::setFileCallback(%p, %p)", func, ptr);
  927. pData->fileCallback = func;
  928. pData->fileCallbackPtr = ptr;
  929. }
  930. // -----------------------------------------------------------------------
  931. // Transport
  932. void CarlaEngine::transportPlay() noexcept
  933. {
  934. pData->time.playing = true;
  935. }
  936. void CarlaEngine::transportPause() noexcept
  937. {
  938. pData->time.playing = false;
  939. }
  940. void CarlaEngine::transportRelocate(const uint64_t frame) noexcept
  941. {
  942. pData->time.frame = frame;
  943. }
  944. // -----------------------------------------------------------------------
  945. // Error handling
  946. const char* CarlaEngine::getLastError() const noexcept
  947. {
  948. return pData->lastError;
  949. }
  950. void CarlaEngine::setLastError(const char* const error) const noexcept
  951. {
  952. pData->lastError = error;
  953. }
  954. void CarlaEngine::setAboutToClose() noexcept
  955. {
  956. carla_debug("CarlaEngine::setAboutToClose()");
  957. pData->aboutToClose = true;
  958. }
  959. // -----------------------------------------------------------------------
  960. // Global options
  961. void CarlaEngine::setOption(const EngineOption option, const int value, const char* const valueStr) noexcept
  962. {
  963. carla_debug("CarlaEngine::setOption(%i:%s, %i, \"%s\")", option, EngineOption2Str(option), value, valueStr);
  964. if (isRunning() && (option == ENGINE_OPTION_PROCESS_MODE || option == ENGINE_OPTION_AUDIO_NUM_PERIODS || option == ENGINE_OPTION_AUDIO_DEVICE))
  965. return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Cannot set this option while engine is running!", option, EngineOption2Str(option), value, valueStr);
  966. if (option == ENGINE_OPTION_FORCE_STEREO && pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  967. {
  968. // do not un-force stereo for rack mode
  969. CARLA_SAFE_ASSERT_RETURN(value == 1,);
  970. }
  971. switch (option)
  972. {
  973. case ENGINE_OPTION_DEBUG:
  974. case ENGINE_OPTION_NSM_INIT:
  975. break;
  976. case ENGINE_OPTION_PROCESS_MODE:
  977. CARLA_SAFE_ASSERT_RETURN(value >= ENGINE_PROCESS_MODE_SINGLE_CLIENT && value <= ENGINE_PROCESS_MODE_BRIDGE,);
  978. pData->options.processMode = static_cast<EngineProcessMode>(value);
  979. break;
  980. case ENGINE_OPTION_TRANSPORT_MODE:
  981. CARLA_SAFE_ASSERT_RETURN(value >= ENGINE_TRANSPORT_MODE_INTERNAL && value <= ENGINE_TRANSPORT_MODE_BRIDGE,);
  982. pData->options.transportMode = static_cast<EngineTransportMode>(value);
  983. break;
  984. case ENGINE_OPTION_FORCE_STEREO:
  985. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  986. pData->options.forceStereo = (value != 0);
  987. break;
  988. case ENGINE_OPTION_PREFER_PLUGIN_BRIDGES:
  989. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  990. pData->options.preferPluginBridges = (value != 0);
  991. break;
  992. case ENGINE_OPTION_PREFER_UI_BRIDGES:
  993. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  994. pData->options.preferUiBridges = (value != 0);
  995. break;
  996. case ENGINE_OPTION_UIS_ALWAYS_ON_TOP:
  997. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  998. pData->options.uisAlwaysOnTop = (value != 0);
  999. break;
  1000. case ENGINE_OPTION_MAX_PARAMETERS:
  1001. CARLA_SAFE_ASSERT_RETURN(value >= 0,);
  1002. pData->options.maxParameters = static_cast<uint>(value);
  1003. break;
  1004. case ENGINE_OPTION_UI_BRIDGES_TIMEOUT:
  1005. CARLA_SAFE_ASSERT_RETURN(value >= 0,);
  1006. pData->options.uiBridgesTimeout = static_cast<uint>(value);
  1007. break;
  1008. case ENGINE_OPTION_AUDIO_NUM_PERIODS:
  1009. CARLA_SAFE_ASSERT_RETURN(value >= 2 && value <= 3,);
  1010. pData->options.audioNumPeriods = static_cast<uint>(value);
  1011. break;
  1012. case ENGINE_OPTION_AUDIO_BUFFER_SIZE:
  1013. CARLA_SAFE_ASSERT_RETURN(value >= 8,);
  1014. pData->options.audioBufferSize = static_cast<uint>(value);
  1015. break;
  1016. case ENGINE_OPTION_AUDIO_SAMPLE_RATE:
  1017. CARLA_SAFE_ASSERT_RETURN(value >= 22050,);
  1018. pData->options.audioSampleRate = static_cast<uint>(value);
  1019. break;
  1020. case ENGINE_OPTION_AUDIO_DEVICE:
  1021. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,);
  1022. if (pData->options.audioDevice != nullptr)
  1023. delete[] pData->options.audioDevice;
  1024. pData->options.audioDevice = carla_strdup_safe(valueStr);
  1025. break;
  1026. case ENGINE_OPTION_PLUGIN_PATH:
  1027. CARLA_SAFE_ASSERT_RETURN(value > PLUGIN_NONE,);
  1028. CARLA_SAFE_ASSERT_RETURN(value <= PLUGIN_SFZ,);
  1029. switch (value)
  1030. {
  1031. case PLUGIN_LADSPA:
  1032. if (pData->options.pathLADSPA != nullptr)
  1033. delete[] pData->options.pathLADSPA;
  1034. if (valueStr != nullptr)
  1035. pData->options.pathLADSPA = carla_strdup_safe(valueStr);
  1036. else
  1037. pData->options.pathLADSPA = nullptr;
  1038. break;
  1039. case PLUGIN_DSSI:
  1040. if (pData->options.pathDSSI != nullptr)
  1041. delete[] pData->options.pathDSSI;
  1042. if (valueStr != nullptr)
  1043. pData->options.pathDSSI = carla_strdup_safe(valueStr);
  1044. else
  1045. pData->options.pathDSSI = nullptr;
  1046. break;
  1047. case PLUGIN_LV2:
  1048. if (pData->options.pathLV2 != nullptr)
  1049. delete[] pData->options.pathLV2;
  1050. if (valueStr != nullptr)
  1051. pData->options.pathLV2 = carla_strdup_safe(valueStr);
  1052. else
  1053. pData->options.pathLV2 = nullptr;
  1054. break;
  1055. case PLUGIN_VST:
  1056. if (pData->options.pathVST != nullptr)
  1057. delete[] pData->options.pathVST;
  1058. if (valueStr != nullptr)
  1059. pData->options.pathVST = carla_strdup_safe(valueStr);
  1060. else
  1061. pData->options.pathVST = nullptr;
  1062. break;
  1063. case PLUGIN_VST3:
  1064. if (pData->options.pathVST3 != nullptr)
  1065. delete[] pData->options.pathVST3;
  1066. if (valueStr != nullptr)
  1067. pData->options.pathVST3 = carla_strdup_safe(valueStr);
  1068. else
  1069. pData->options.pathVST3 = nullptr;
  1070. break;
  1071. case PLUGIN_AU:
  1072. if (pData->options.pathAU != nullptr)
  1073. delete[] pData->options.pathAU;
  1074. if (valueStr != nullptr)
  1075. pData->options.pathAU = carla_strdup_safe(valueStr);
  1076. else
  1077. pData->options.pathAU = nullptr;
  1078. break;
  1079. case PLUGIN_GIG:
  1080. if (pData->options.pathGIG != nullptr)
  1081. delete[] pData->options.pathGIG;
  1082. if (valueStr != nullptr)
  1083. pData->options.pathGIG = carla_strdup_safe(valueStr);
  1084. else
  1085. pData->options.pathGIG = nullptr;
  1086. break;
  1087. case PLUGIN_SF2:
  1088. if (pData->options.pathSF2 != nullptr)
  1089. delete[] pData->options.pathSF2;
  1090. if (valueStr != nullptr)
  1091. pData->options.pathSF2 = carla_strdup_safe(valueStr);
  1092. else
  1093. pData->options.pathSF2 = nullptr;
  1094. break;
  1095. case PLUGIN_SFZ:
  1096. if (pData->options.pathSFZ != nullptr)
  1097. delete[] pData->options.pathSFZ;
  1098. if (valueStr != nullptr)
  1099. pData->options.pathSFZ = carla_strdup_safe(valueStr);
  1100. else
  1101. pData->options.pathSFZ = nullptr;
  1102. break;
  1103. }
  1104. break;
  1105. case ENGINE_OPTION_PATH_BINARIES:
  1106. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1107. if (pData->options.binaryDir != nullptr)
  1108. delete[] pData->options.binaryDir;
  1109. pData->options.binaryDir = carla_strdup_safe(valueStr);
  1110. break;
  1111. case ENGINE_OPTION_PATH_RESOURCES:
  1112. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1113. if (pData->options.resourceDir != nullptr)
  1114. delete[] pData->options.resourceDir;
  1115. pData->options.resourceDir = carla_strdup_safe(valueStr);
  1116. break;
  1117. case ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR:
  1118. CARLA_SAFE_ASSERT_RETURN(pData->options.binaryDir != nullptr && pData->options.binaryDir[0] != '\0',);
  1119. #ifdef CARLA_OS_LINUX
  1120. if (value != 0)
  1121. {
  1122. CarlaString interposerPath(CarlaString(pData->options.binaryDir) + CARLA_OS_SEP_STR "libcarla_interposer.so");
  1123. ::setenv("LD_PRELOAD", interposerPath.buffer(), 1);
  1124. }
  1125. else
  1126. {
  1127. ::unsetenv("LD_PRELOAD");
  1128. }
  1129. #endif
  1130. break;
  1131. case ENGINE_OPTION_FRONTEND_WIN_ID:
  1132. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1133. const long long winId(std::strtoll(valueStr, nullptr, 16));
  1134. CARLA_SAFE_ASSERT_RETURN(winId >= 0,);
  1135. pData->options.frontendWinId = static_cast<uintptr_t>(winId);
  1136. break;
  1137. }
  1138. }
  1139. // -----------------------------------------------------------------------
  1140. // OSC Stuff
  1141. #ifdef BUILD_BRIDGE
  1142. bool CarlaEngine::isOscBridgeRegistered() const noexcept
  1143. {
  1144. return (pData->oscData != nullptr);
  1145. }
  1146. #else
  1147. bool CarlaEngine::isOscControlRegistered() const noexcept
  1148. {
  1149. return pData->osc.isControlRegistered();
  1150. }
  1151. #endif
  1152. void CarlaEngine::idleOsc() const noexcept
  1153. {
  1154. pData->osc.idle();
  1155. }
  1156. const char* CarlaEngine::getOscServerPathTCP() const noexcept
  1157. {
  1158. return pData->osc.getServerPathTCP();
  1159. }
  1160. const char* CarlaEngine::getOscServerPathUDP() const noexcept
  1161. {
  1162. return pData->osc.getServerPathUDP();
  1163. }
  1164. #ifdef BUILD_BRIDGE
  1165. void CarlaEngine::setOscBridgeData(CarlaOscData* const oscData) const noexcept
  1166. {
  1167. pData->oscData = oscData;
  1168. }
  1169. #endif
  1170. // -----------------------------------------------------------------------
  1171. // Helper functions
  1172. EngineEvent* CarlaEngine::getInternalEventBuffer(const bool isInput) const noexcept
  1173. {
  1174. return isInput ? pData->events.in : pData->events.out;
  1175. }
  1176. void CarlaEngine::registerEnginePlugin(const uint id, CarlaPlugin* const plugin) noexcept
  1177. {
  1178. CARLA_SAFE_ASSERT_RETURN(id == pData->curPluginCount,);
  1179. carla_debug("CarlaEngine::registerEnginePlugin(%i, %p)", id, plugin);
  1180. pData->plugins[id].plugin = plugin;
  1181. }
  1182. // -----------------------------------------------------------------------
  1183. // Internal stuff
  1184. void CarlaEngine::bufferSizeChanged(const uint32_t newBufferSize)
  1185. {
  1186. carla_debug("CarlaEngine::bufferSizeChanged(%i)", newBufferSize);
  1187. #ifndef BUILD_BRIDGE
  1188. pData->graph.setBufferSize(newBufferSize);
  1189. #endif
  1190. for (uint i=0; i < pData->curPluginCount; ++i)
  1191. {
  1192. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1193. if (plugin != nullptr && plugin->isEnabled())
  1194. plugin->bufferSizeChanged(newBufferSize);
  1195. }
  1196. callback(ENGINE_CALLBACK_BUFFER_SIZE_CHANGED, 0, static_cast<int>(newBufferSize), 0, 0.0f, nullptr);
  1197. }
  1198. void CarlaEngine::sampleRateChanged(const double newSampleRate)
  1199. {
  1200. carla_debug("CarlaEngine::sampleRateChanged(%g)", newSampleRate);
  1201. #ifndef BUILD_BRIDGE
  1202. pData->graph.setSampleRate(newSampleRate);
  1203. #endif
  1204. for (uint i=0; i < pData->curPluginCount; ++i)
  1205. {
  1206. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1207. if (plugin != nullptr && plugin->isEnabled())
  1208. plugin->sampleRateChanged(newSampleRate);
  1209. }
  1210. callback(ENGINE_CALLBACK_SAMPLE_RATE_CHANGED, 0, 0, 0, static_cast<float>(newSampleRate), nullptr);
  1211. }
  1212. void CarlaEngine::offlineModeChanged(const bool isOfflineNow)
  1213. {
  1214. carla_debug("CarlaEngine::offlineModeChanged(%s)", bool2str(isOfflineNow));
  1215. #ifndef BUILD_BRIDGE
  1216. pData->graph.setOffline(isOfflineNow);
  1217. #endif
  1218. for (uint i=0; i < pData->curPluginCount; ++i)
  1219. {
  1220. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1221. if (plugin != nullptr && plugin->isEnabled())
  1222. plugin->offlineModeChanged(isOfflineNow);
  1223. }
  1224. }
  1225. void CarlaEngine::runPendingRtEvents() noexcept
  1226. {
  1227. pData->doNextPluginAction(true);
  1228. if (pData->time.playing)
  1229. pData->time.frame += pData->bufferSize;
  1230. if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
  1231. {
  1232. pData->timeInfo.playing = pData->time.playing;
  1233. pData->timeInfo.frame = pData->time.frame;
  1234. }
  1235. }
  1236. void CarlaEngine::setPluginPeaks(const uint pluginId, float const inPeaks[2], float const outPeaks[2]) noexcept
  1237. {
  1238. EnginePluginData& pluginData(pData->plugins[pluginId]);
  1239. pluginData.insPeak[0] = inPeaks[0];
  1240. pluginData.insPeak[1] = inPeaks[1];
  1241. pluginData.outsPeak[0] = outPeaks[0];
  1242. pluginData.outsPeak[1] = outPeaks[1];
  1243. }
  1244. void CarlaEngine::saveProjectInternal(juce::MemoryOutputStream& outStream) const
  1245. {
  1246. outStream << "<?xml version='1.0' encoding='UTF-8'?>\n";
  1247. outStream << "<!DOCTYPE CARLA-PROJECT>\n";
  1248. outStream << "<CARLA-PROJECT VERSION='2.0'>\n";
  1249. const bool isPlugin(std::strcmp(getCurrentDriverName(), "Plugin") == 0);
  1250. const EngineOptions& options(pData->options);
  1251. MemoryOutputStream outSettings(1024);
  1252. // save appropriate engine settings
  1253. outSettings << " <EngineSettings>\n";
  1254. //processMode
  1255. //transportMode
  1256. outSettings << " <ForceStereo>" << bool2str(options.forceStereo) << "</ForceStereo>\n";
  1257. outSettings << " <PreferPluginBridges>" << bool2str(options.preferPluginBridges) << "</PreferPluginBridges>\n";
  1258. outSettings << " <PreferUiBridges>" << bool2str(options.preferUiBridges) << "</PreferUiBridges>\n";
  1259. outSettings << " <UIsAlwaysOnTop>" << bool2str(options.uisAlwaysOnTop) << "</UIsAlwaysOnTop>\n";
  1260. outSettings << " <MaxParameters>" << String(options.maxParameters) << "</MaxParameters>\n";
  1261. outSettings << " <UIBridgesTimeout>" << String(options.uiBridgesTimeout) << "</UIBridgesTimeout>\n";
  1262. if (isPlugin)
  1263. {
  1264. outSettings << " <LADSPA_PATH>" << xmlSafeString(options.pathLADSPA, true) << "</LADSPA_PATH>\n";
  1265. outSettings << " <DSSI_PATH>" << xmlSafeString(options.pathDSSI, true) << "</DSSI_PATH>\n";
  1266. outSettings << " <LV2_PATH>" << xmlSafeString(options.pathLV2, true) << "</LV2_PATH>\n";
  1267. outSettings << " <VST_PATH>" << xmlSafeString(options.pathVST, true) << "</VST_PATH>\n";
  1268. outSettings << " <VST3_PATH>" << xmlSafeString(options.pathVST3, true) << "</VST3_PATH>\n";
  1269. outSettings << " <AU_PATH>" << xmlSafeString(options.pathAU, true) << "</AU_PATH>\n";
  1270. outSettings << " <GIG_PATH>" << xmlSafeString(options.pathGIG, true) << "</GIG_PATH>\n";
  1271. outSettings << " <SF2_PATH>" << xmlSafeString(options.pathSF2, true) << "</SF2_PATH>\n";
  1272. outSettings << " <SFZ_PATH>" << xmlSafeString(options.pathSFZ, true) << "</SFZ_PATH>\n";
  1273. }
  1274. outSettings << " </EngineSettings>\n";
  1275. outStream << outSettings;
  1276. char strBuf[STR_MAX+1];
  1277. for (uint i=0; i < pData->curPluginCount; ++i)
  1278. {
  1279. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1280. if (plugin != nullptr && plugin->isEnabled())
  1281. {
  1282. MemoryOutputStream outPlugin(4096);
  1283. outPlugin << "\n";
  1284. strBuf[0] = '\0';
  1285. plugin->getRealName(strBuf);
  1286. if (strBuf[0] != '\0')
  1287. outPlugin << " <!-- " << xmlSafeString(strBuf, true) << " -->\n";
  1288. outPlugin << " <Plugin>\n";
  1289. outPlugin << plugin->getStateSave().toString();
  1290. outPlugin << " </Plugin>\n";
  1291. outStream << outPlugin;
  1292. }
  1293. }
  1294. #ifndef BUILD_BRIDGE
  1295. bool saveConnections = true;
  1296. // if we're running inside some session-manager, let them handle the connections
  1297. if (pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY)
  1298. {
  1299. /**/ if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr)
  1300. saveConnections = false;
  1301. else if (std::getenv("LADISH_APP_NAME") != nullptr)
  1302. saveConnections = false;
  1303. else if (std::getenv("NSM_URL") != nullptr)
  1304. saveConnections = false;
  1305. else if (std::strcmp(getCurrentDriverName(), "Plugin") == 0)
  1306. saveConnections = false;
  1307. }
  1308. if (saveConnections)
  1309. {
  1310. if (const char* const* const patchbayConns = getPatchbayConnections())
  1311. {
  1312. MemoryOutputStream outPatchbay(2048);
  1313. outPatchbay << "\n <Patchbay>\n";
  1314. for (int i=0; patchbayConns[i] != nullptr && patchbayConns[i+1] != nullptr; ++i, ++i )
  1315. {
  1316. const char* const connSource(patchbayConns[i]);
  1317. const char* const connTarget(patchbayConns[i+1]);
  1318. CARLA_SAFE_ASSERT_CONTINUE(connSource != nullptr && connSource[0] != '\0');
  1319. CARLA_SAFE_ASSERT_CONTINUE(connTarget != nullptr && connTarget[0] != '\0');
  1320. outPatchbay << " <Connection>\n";
  1321. outPatchbay << " <Source>" << connSource << "</Source>\n";
  1322. outPatchbay << " <Target>" << connTarget << "</Target>\n";
  1323. outPatchbay << " </Connection>\n";
  1324. }
  1325. outPatchbay << " </Patchbay>\n";
  1326. outStream << outPatchbay;
  1327. }
  1328. }
  1329. #endif
  1330. outStream << "</CARLA-PROJECT>\n";
  1331. }
  1332. bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc)
  1333. {
  1334. ScopedPointer<XmlElement> xmlElement(xmlDoc.getDocumentElement(true));
  1335. CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to parse project file");
  1336. const String& xmlType(xmlElement->getTagName());
  1337. const bool isPreset(xmlType.equalsIgnoreCase("carla-preset"));
  1338. if (! (xmlType.equalsIgnoreCase("carla-project") || isPreset))
  1339. {
  1340. setLastError("Not a valid Carla project or preset file");
  1341. return false;
  1342. }
  1343. // completely load file
  1344. xmlElement = xmlDoc.getDocumentElement(false);
  1345. CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to completely parse project file");
  1346. const bool isPlugin(std::strcmp(getCurrentDriverName(), "Plugin") == 0);
  1347. // engine settings
  1348. for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
  1349. {
  1350. const String& tagName(elem->getTagName());
  1351. if (! tagName.equalsIgnoreCase("enginesettings"))
  1352. continue;
  1353. for (XmlElement* settElem = elem->getFirstChildElement(); settElem != nullptr; settElem = settElem->getNextElement())
  1354. {
  1355. const String& tag(settElem->getTagName());
  1356. const String text(settElem->getAllSubText().trim());
  1357. /** some settings might be incorrect or require extra work,
  1358. so we call setOption rather than modifying them direly */
  1359. int option = -1;
  1360. int value = 0;
  1361. const char* valueStr = nullptr;
  1362. /**/ if (tag.equalsIgnoreCase("forcestereo"))
  1363. {
  1364. option = ENGINE_OPTION_FORCE_STEREO;
  1365. value = text.equalsIgnoreCase("true") ? 1 : 0;
  1366. }
  1367. else if (tag.equalsIgnoreCase("preferpluginbridges"))
  1368. {
  1369. option = ENGINE_OPTION_PREFER_PLUGIN_BRIDGES;
  1370. value = text.equalsIgnoreCase("true") ? 1 : 0;
  1371. }
  1372. else if (tag.equalsIgnoreCase("preferuibridges"))
  1373. {
  1374. option = ENGINE_OPTION_PREFER_UI_BRIDGES;
  1375. value = text.equalsIgnoreCase("true") ? 1 : 0;
  1376. }
  1377. else if (tag.equalsIgnoreCase("uisalwaysontop"))
  1378. {
  1379. option = ENGINE_OPTION_UIS_ALWAYS_ON_TOP;
  1380. value = text.equalsIgnoreCase("true") ? 1 : 0;
  1381. }
  1382. else if (tag.equalsIgnoreCase("maxparameters"))
  1383. {
  1384. option = ENGINE_OPTION_MAX_PARAMETERS;
  1385. value = text.getIntValue();
  1386. }
  1387. else if (tag.equalsIgnoreCase("uibridgestimeout"))
  1388. {
  1389. option = ENGINE_OPTION_UI_BRIDGES_TIMEOUT;
  1390. value = text.getIntValue();
  1391. }
  1392. else if (isPlugin)
  1393. {
  1394. /**/ if (tag.equalsIgnoreCase("LADSPA_PATH"))
  1395. {
  1396. option = ENGINE_OPTION_PLUGIN_PATH;
  1397. value = PLUGIN_LADSPA;
  1398. valueStr = text.toRawUTF8();
  1399. }
  1400. else if (tag.equalsIgnoreCase("DSSI_PATH"))
  1401. {
  1402. option = ENGINE_OPTION_PLUGIN_PATH;
  1403. value = PLUGIN_DSSI;
  1404. valueStr = text.toRawUTF8();
  1405. }
  1406. else if (tag.equalsIgnoreCase("LV2_PATH"))
  1407. {
  1408. option = ENGINE_OPTION_PLUGIN_PATH;
  1409. value = PLUGIN_LV2;
  1410. valueStr = text.toRawUTF8();
  1411. }
  1412. else if (tag.equalsIgnoreCase("VST_PATH"))
  1413. {
  1414. option = ENGINE_OPTION_PLUGIN_PATH;
  1415. value = PLUGIN_VST;
  1416. valueStr = text.toRawUTF8();
  1417. }
  1418. else if (tag.equalsIgnoreCase("VST3_PATH"))
  1419. {
  1420. option = ENGINE_OPTION_PLUGIN_PATH;
  1421. value = PLUGIN_VST3;
  1422. valueStr = text.toRawUTF8();
  1423. }
  1424. else if (tag.equalsIgnoreCase("AU_PATH"))
  1425. {
  1426. option = ENGINE_OPTION_PLUGIN_PATH;
  1427. value = PLUGIN_AU;
  1428. valueStr = text.toRawUTF8();
  1429. }
  1430. else if (tag.equalsIgnoreCase("GIG_PATH"))
  1431. {
  1432. option = ENGINE_OPTION_PLUGIN_PATH;
  1433. value = PLUGIN_GIG;
  1434. valueStr = text.toRawUTF8();
  1435. }
  1436. else if (tag.equalsIgnoreCase("SF2_PATH"))
  1437. {
  1438. option = ENGINE_OPTION_PLUGIN_PATH;
  1439. value = PLUGIN_SF2;
  1440. valueStr = text.toRawUTF8();
  1441. }
  1442. else if (tag.equalsIgnoreCase("SFZ_PATH"))
  1443. {
  1444. option = ENGINE_OPTION_PLUGIN_PATH;
  1445. value = PLUGIN_SFZ;
  1446. valueStr = text.toRawUTF8();
  1447. }
  1448. }
  1449. CARLA_SAFE_ASSERT_CONTINUE(option != -1);
  1450. setOption(static_cast<EngineOption>(option), value, valueStr);
  1451. }
  1452. break;
  1453. }
  1454. // handle plugins first
  1455. for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
  1456. {
  1457. const String& tagName(elem->getTagName());
  1458. if (isPreset || tagName.equalsIgnoreCase("plugin"))
  1459. {
  1460. StateSave stateSave;
  1461. stateSave.fillFromXmlElement(isPreset ? xmlElement.get() : elem);
  1462. callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  1463. CARLA_SAFE_ASSERT_CONTINUE(stateSave.type != nullptr);
  1464. const void* extraStuff = nullptr;
  1465. // check if using GIG or SF2 16outs
  1466. static const char kUse16OutsSuffix[] = " (16 outs)";
  1467. const BinaryType btype(getBinaryTypeFromFile(stateSave.binary));
  1468. const PluginType ptype(getPluginTypeFromString(stateSave.type));
  1469. if (CarlaString(stateSave.label).endsWith(kUse16OutsSuffix))
  1470. {
  1471. if (ptype == PLUGIN_GIG || ptype == PLUGIN_SF2)
  1472. extraStuff = "true";
  1473. }
  1474. // TODO - proper find&load plugins
  1475. if (addPlugin(btype, ptype, stateSave.binary, stateSave.name, stateSave.label, stateSave.uniqueId, extraStuff))
  1476. {
  1477. if (CarlaPlugin* const plugin = getPlugin(pData->curPluginCount-1))
  1478. plugin->loadStateSave(stateSave);
  1479. }
  1480. else
  1481. carla_stderr2("Failed to load a plugin, error was:\n%s", getLastError());
  1482. }
  1483. if (isPreset)
  1484. return true;
  1485. }
  1486. #ifndef BUILD_BRIDGE
  1487. callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  1488. // if we're running inside some session-manager, let them handle the connections
  1489. if (pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY)
  1490. {
  1491. /**/ if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr)
  1492. return true;
  1493. else if (std::getenv("LADISH_APP_NAME") != nullptr)
  1494. return true;
  1495. else if (std::getenv("NSM_URL") != nullptr)
  1496. return true;
  1497. else if (std::strcmp(getCurrentDriverName(), "Plugin") == 0)
  1498. return true;
  1499. }
  1500. // now handle connections
  1501. for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
  1502. {
  1503. const String& tagName(elem->getTagName());
  1504. if (! tagName.equalsIgnoreCase("patchbay"))
  1505. continue;
  1506. CarlaString sourcePort, targetPort;
  1507. for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement())
  1508. {
  1509. const String& patchTag(patchElem->getTagName());
  1510. sourcePort.clear();
  1511. targetPort.clear();
  1512. if (! patchTag.equalsIgnoreCase("connection"))
  1513. continue;
  1514. for (XmlElement* connElem = patchElem->getFirstChildElement(); connElem != nullptr; connElem = connElem->getNextElement())
  1515. {
  1516. const String& tag(connElem->getTagName());
  1517. const String text(connElem->getAllSubText().trim());
  1518. /**/ if (tag.equalsIgnoreCase("source"))
  1519. sourcePort = text.toRawUTF8();
  1520. else if (tag.equalsIgnoreCase("target"))
  1521. targetPort = text.toRawUTF8();
  1522. }
  1523. if (sourcePort.isNotEmpty() && targetPort.isNotEmpty())
  1524. restorePatchbayConnection(sourcePort, targetPort);
  1525. }
  1526. break;
  1527. }
  1528. #endif
  1529. return true;
  1530. }
  1531. // -----------------------------------------------------------------------
  1532. CARLA_BACKEND_END_NAMESPACE