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 49KB

11 years ago
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
11 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
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
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
11 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
11 years ago
10 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
10 years ago
10 years ago
11 years ago
10 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
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
10 years ago
10 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
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
11 years ago
11 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
10 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
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
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
11 years ago
10 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
11 years ago
10 years ago
11 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
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
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550
  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