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

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