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

11 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
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
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
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
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
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
7 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
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
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
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
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
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
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 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
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883
  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2019 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. * - something about the peaks?
  22. */
  23. #include "CarlaEngineInternal.hpp"
  24. #include "CarlaPlugin.hpp"
  25. #include "CarlaBackendUtils.hpp"
  26. #include "CarlaBinaryUtils.hpp"
  27. #include "CarlaEngineUtils.hpp"
  28. #include "CarlaMathUtils.hpp"
  29. #include "CarlaPipeUtils.hpp"
  30. #include "CarlaProcessUtils.hpp"
  31. #include "CarlaScopeUtils.hpp"
  32. #include "CarlaStateUtils.hpp"
  33. #include "CarlaMIDI.h"
  34. #include "jackbridge/JackBridge.hpp"
  35. #include "water/files/File.h"
  36. #include "water/streams/MemoryOutputStream.h"
  37. #include "water/xml/XmlDocument.h"
  38. #include "water/xml/XmlElement.h"
  39. // FIXME Remove on 2.1 release
  40. #include "lv2/atom.h"
  41. using water::Array;
  42. using water::CharPointer_UTF8;
  43. using water::File;
  44. using water::MemoryOutputStream;
  45. using water::String;
  46. using water::StringArray;
  47. using water::XmlDocument;
  48. using water::XmlElement;
  49. CARLA_BACKEND_START_NAMESPACE
  50. // -----------------------------------------------------------------------
  51. // Carla Engine
  52. CarlaEngine::CarlaEngine()
  53. : pData(new ProtectedData(this))
  54. {
  55. carla_debug("CarlaEngine::CarlaEngine()");
  56. }
  57. CarlaEngine::~CarlaEngine()
  58. {
  59. carla_debug("CarlaEngine::~CarlaEngine()");
  60. delete pData;
  61. }
  62. // -----------------------------------------------------------------------
  63. // Static calls
  64. uint CarlaEngine::getDriverCount()
  65. {
  66. carla_debug("CarlaEngine::getDriverCount()");
  67. uint count = 0;
  68. if (jackbridge_is_ok())
  69. count += 1;
  70. #ifndef BUILD_BRIDGE
  71. # ifdef USING_JUCE
  72. count += getJuceApiCount();
  73. # else
  74. count += getRtAudioApiCount();
  75. # endif
  76. #endif
  77. return count;
  78. }
  79. const char* CarlaEngine::getDriverName(const uint index2)
  80. {
  81. carla_debug("CarlaEngine::getDriverName(%i)", index2);
  82. uint index = index2;
  83. if (jackbridge_is_ok() && index-- == 0)
  84. return "JACK";
  85. #ifndef BUILD_BRIDGE
  86. # ifdef USING_JUCE
  87. if (const uint count = getJuceApiCount())
  88. {
  89. if (index < count)
  90. return getJuceApiName(index);
  91. index -= count;
  92. }
  93. # else
  94. if (const uint count = getRtAudioApiCount())
  95. {
  96. if (index < count)
  97. return getRtAudioApiName(index);
  98. }
  99. # endif
  100. #endif
  101. carla_stderr("CarlaEngine::getDriverName(%i) - invalid index", index2);
  102. return nullptr;
  103. }
  104. const char* const* CarlaEngine::getDriverDeviceNames(const uint index2)
  105. {
  106. carla_debug("CarlaEngine::getDriverDeviceNames(%i)", index2);
  107. uint index = index2;
  108. if (jackbridge_is_ok() && index-- == 0)
  109. {
  110. static const char* ret[3] = { "Auto-Connect ON", "Auto-Connect OFF", nullptr };
  111. return ret;
  112. }
  113. #ifndef BUILD_BRIDGE
  114. # ifdef USING_JUCE
  115. if (const uint count = getJuceApiCount())
  116. {
  117. if (index < count)
  118. return getJuceApiDeviceNames(index);
  119. index -= count;
  120. }
  121. # else
  122. if (const uint count = getRtAudioApiCount())
  123. {
  124. if (index < count)
  125. return getRtAudioApiDeviceNames(index);
  126. }
  127. # endif
  128. #endif
  129. carla_stderr("CarlaEngine::getDriverDeviceNames(%i) - invalid index", index2);
  130. return nullptr;
  131. }
  132. const EngineDriverDeviceInfo* CarlaEngine::getDriverDeviceInfo(const uint index2, const char* const deviceName)
  133. {
  134. carla_debug("CarlaEngine::getDriverDeviceInfo(%i, \"%s\")", index2, deviceName);
  135. uint index = index2;
  136. if (jackbridge_is_ok() && index-- == 0)
  137. {
  138. static EngineDriverDeviceInfo devInfo;
  139. devInfo.hints = ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE;
  140. devInfo.bufferSizes = nullptr;
  141. devInfo.sampleRates = nullptr;
  142. return &devInfo;
  143. }
  144. #ifndef BUILD_BRIDGE
  145. # ifdef USING_JUCE
  146. if (const uint count = getJuceApiCount())
  147. {
  148. if (index < count)
  149. return getJuceDeviceInfo(index, deviceName);
  150. index -= count;
  151. }
  152. # else
  153. if (const uint count = getRtAudioApiCount())
  154. {
  155. if (index < count)
  156. return getRtAudioDeviceInfo(index, deviceName);
  157. }
  158. # endif
  159. #endif
  160. carla_stderr("CarlaEngine::getDriverDeviceNames(%i, \"%s\") - invalid index", index2, deviceName);
  161. return nullptr;
  162. }
  163. bool CarlaEngine::showDriverDeviceControlPanel(const uint index2, const char* const deviceName)
  164. {
  165. carla_debug("CarlaEngine::showDriverDeviceControlPanel(%i, \"%s\")", index2, deviceName);
  166. uint index = index2;
  167. if (jackbridge_is_ok() && index-- == 0)
  168. {
  169. return false;
  170. }
  171. #ifndef BUILD_BRIDGE
  172. # ifdef USING_JUCE
  173. if (const uint count = getJuceApiCount())
  174. {
  175. if (index < count)
  176. return showJuceDeviceControlPanel(index, deviceName);
  177. index -= count;
  178. }
  179. # else
  180. if (const uint count = getRtAudioApiCount())
  181. {
  182. if (index < count)
  183. return false;
  184. }
  185. # endif
  186. #endif
  187. carla_stderr("CarlaEngine::showDriverDeviceControlPanel(%i, \"%s\") - invalid index", index2, deviceName);
  188. return false;
  189. }
  190. CarlaEngine* CarlaEngine::newDriverByName(const char* const driverName)
  191. {
  192. CARLA_SAFE_ASSERT_RETURN(driverName != nullptr && driverName[0] != '\0', nullptr);
  193. carla_debug("CarlaEngine::newDriverByName(\"%s\")", driverName);
  194. if (std::strcmp(driverName, "JACK") == 0)
  195. return newJack();
  196. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  197. if (std::strcmp(driverName, "Dummy") == 0)
  198. return newDummy();
  199. #endif
  200. #ifndef BUILD_BRIDGE
  201. # ifdef USING_JUCE
  202. // -------------------------------------------------------------------
  203. // linux
  204. if (std::strcmp(driverName, "ALSA") == 0)
  205. return newJuce(AUDIO_API_ALSA);
  206. // -------------------------------------------------------------------
  207. // macos
  208. if (std::strcmp(driverName, "CoreAudio") == 0)
  209. return newJuce(AUDIO_API_COREAUDIO);
  210. // -------------------------------------------------------------------
  211. // windows
  212. if (std::strcmp(driverName, "ASIO") == 0)
  213. return newJuce(AUDIO_API_ASIO);
  214. if (std::strcmp(driverName, "DirectSound") == 0)
  215. return newJuce(AUDIO_API_DIRECTSOUND);
  216. if (std::strcmp(driverName, "WASAPI") == 0 || std::strcmp(driverName, "Windows Audio") == 0)
  217. return newJuce(AUDIO_API_WASAPI);
  218. # else
  219. // -------------------------------------------------------------------
  220. // common
  221. if (std::strncmp(driverName, "JACK ", 5) == 0)
  222. return newRtAudio(AUDIO_API_JACK);
  223. if (std::strcmp(driverName, "OSS") == 0)
  224. return newRtAudio(AUDIO_API_OSS);
  225. // -------------------------------------------------------------------
  226. // linux
  227. if (std::strcmp(driverName, "ALSA") == 0)
  228. return newRtAudio(AUDIO_API_ALSA);
  229. if (std::strcmp(driverName, "PulseAudio") == 0)
  230. return newRtAudio(AUDIO_API_PULSEAUDIO);
  231. // -------------------------------------------------------------------
  232. // macos
  233. if (std::strcmp(driverName, "CoreAudio") == 0)
  234. return newRtAudio(AUDIO_API_COREAUDIO);
  235. // -------------------------------------------------------------------
  236. // windows
  237. if (std::strcmp(driverName, "ASIO") == 0)
  238. return newRtAudio(AUDIO_API_ASIO);
  239. if (std::strcmp(driverName, "DirectSound") == 0)
  240. return newRtAudio(AUDIO_API_DIRECTSOUND);
  241. if (std::strcmp(driverName, "WASAPI") == 0)
  242. return newRtAudio(AUDIO_API_WASAPI);
  243. # endif
  244. #endif
  245. carla_stderr("CarlaEngine::newDriverByName(\"%s\") - invalid driver name", driverName);
  246. return nullptr;
  247. }
  248. // -----------------------------------------------------------------------
  249. // Constant values
  250. uint CarlaEngine::getMaxClientNameSize() const noexcept
  251. {
  252. return STR_MAX/2;
  253. }
  254. uint CarlaEngine::getMaxPortNameSize() const noexcept
  255. {
  256. return STR_MAX;
  257. }
  258. uint CarlaEngine::getCurrentPluginCount() const noexcept
  259. {
  260. return pData->curPluginCount;
  261. }
  262. uint CarlaEngine::getMaxPluginNumber() const noexcept
  263. {
  264. return pData->maxPluginNumber;
  265. }
  266. // -----------------------------------------------------------------------
  267. // Virtual, per-engine type calls
  268. bool CarlaEngine::close()
  269. {
  270. carla_debug("CarlaEngine::close()");
  271. if (pData->curPluginCount != 0)
  272. {
  273. pData->aboutToClose = true;
  274. removeAllPlugins();
  275. }
  276. pData->close();
  277. callback(true, true, ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0, 0.0f, nullptr);
  278. return true;
  279. }
  280. bool CarlaEngine::usesConstantBufferSize() const noexcept
  281. {
  282. return true;
  283. }
  284. void CarlaEngine::idle() noexcept
  285. {
  286. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,);
  287. CARLA_SAFE_ASSERT_RETURN(pData->nextPluginId == pData->maxPluginNumber,);
  288. CARLA_SAFE_ASSERT_RETURN(getType() != kEngineTypePlugin,);
  289. for (uint i=0; i < pData->curPluginCount; ++i)
  290. {
  291. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  292. if (plugin != nullptr && plugin->isEnabled())
  293. {
  294. const uint hints(plugin->getHints());
  295. if ((hints & PLUGIN_HAS_CUSTOM_UI) != 0 && (hints & PLUGIN_NEEDS_UI_MAIN_THREAD) != 0)
  296. {
  297. try {
  298. plugin->uiIdle();
  299. } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin uiIdle");
  300. }
  301. }
  302. }
  303. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
  304. pData->osc.idle();
  305. #endif
  306. }
  307. CarlaEngineClient* CarlaEngine::addClient(CarlaPlugin* const)
  308. {
  309. return new CarlaEngineClient(*this);
  310. }
  311. float CarlaEngine::getDSPLoad() const noexcept
  312. {
  313. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  314. return pData->dspLoad;
  315. #else
  316. return 0.0f;
  317. #endif
  318. }
  319. uint32_t CarlaEngine::getTotalXruns() const noexcept
  320. {
  321. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  322. return pData->xruns;
  323. #else
  324. return 0;
  325. #endif
  326. }
  327. void CarlaEngine::clearXruns() const noexcept
  328. {
  329. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  330. pData->xruns = 0;
  331. #endif
  332. }
  333. bool CarlaEngine::showDeviceControlPanel() const noexcept
  334. {
  335. return false;
  336. }
  337. bool CarlaEngine::setBufferSizeAndSampleRate(const uint, const double)
  338. {
  339. return false;
  340. }
  341. // -----------------------------------------------------------------------
  342. // Plugin management
  343. bool CarlaEngine::addPlugin(const BinaryType btype,
  344. const PluginType ptype,
  345. const char* const filename,
  346. const char* const name,
  347. const char* const label,
  348. const int64_t uniqueId,
  349. const void* const extra,
  350. const uint options)
  351. {
  352. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  353. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  354. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  355. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextPluginId <= pData->maxPluginNumber, "Invalid engine internal data");
  356. #endif
  357. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  358. CARLA_SAFE_ASSERT_RETURN_ERR(btype != BINARY_NONE, "Invalid plugin binary mode");
  359. CARLA_SAFE_ASSERT_RETURN_ERR(ptype != PLUGIN_NONE, "Invalid plugin type");
  360. CARLA_SAFE_ASSERT_RETURN_ERR((filename != nullptr && filename[0] != '\0') || (label != nullptr && label[0] != '\0'), "Invalid plugin filename and label");
  361. carla_debug("CarlaEngine::addPlugin(%i:%s, %i:%s, \"%s\", \"%s\", \"%s\", " P_INT64 ", %p, %u)",
  362. btype, BinaryType2Str(btype), ptype, PluginType2Str(ptype), filename, name, label, uniqueId, extra, options);
  363. #ifndef CARLA_OS_WIN
  364. if (ptype != PLUGIN_JACK && ptype != PLUGIN_LV2 && filename != nullptr && filename[0] != '\0') {
  365. CARLA_SAFE_ASSERT_RETURN_ERR(filename[0] == CARLA_OS_SEP || filename[0] == '.' || filename[0] == '~', "Invalid plugin filename");
  366. }
  367. #endif
  368. uint id;
  369. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  370. CarlaPlugin* oldPlugin = nullptr;
  371. if (pData->nextPluginId < pData->curPluginCount)
  372. {
  373. id = pData->nextPluginId;
  374. pData->nextPluginId = pData->maxPluginNumber;
  375. oldPlugin = pData->plugins[id].plugin;
  376. CARLA_SAFE_ASSERT_RETURN_ERR(oldPlugin != nullptr, "Invalid replace plugin Id");
  377. }
  378. else
  379. #endif
  380. {
  381. id = pData->curPluginCount;
  382. if (id == pData->maxPluginNumber)
  383. {
  384. setLastError("Maximum number of plugins reached");
  385. return false;
  386. }
  387. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  388. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins[id].plugin == nullptr, "Invalid engine internal data");
  389. #endif
  390. }
  391. CarlaPlugin::Initializer initializer = {
  392. this,
  393. id,
  394. filename,
  395. name,
  396. label,
  397. uniqueId,
  398. options
  399. };
  400. CarlaPlugin* plugin = nullptr;
  401. CarlaString bridgeBinary(pData->options.binaryDir);
  402. if (bridgeBinary.isNotEmpty())
  403. {
  404. #ifndef CARLA_OS_WIN
  405. if (btype == BINARY_NATIVE)
  406. {
  407. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-native";
  408. }
  409. else
  410. #endif
  411. {
  412. switch (btype)
  413. {
  414. case BINARY_POSIX32:
  415. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-posix32";
  416. break;
  417. case BINARY_POSIX64:
  418. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-posix64";
  419. break;
  420. case BINARY_WIN32:
  421. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-win32.exe";
  422. break;
  423. case BINARY_WIN64:
  424. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-win64.exe";
  425. break;
  426. default:
  427. bridgeBinary.clear();
  428. break;
  429. }
  430. }
  431. if (! File(bridgeBinary.buffer()).existsAsFile())
  432. bridgeBinary.clear();
  433. }
  434. // Prefer bridges for some specific plugins
  435. const bool preferBridges = pData->options.preferPluginBridges;
  436. #if 0 // ndef BUILD_BRIDGE
  437. if (! preferBridges)
  438. {
  439. if (ptype == PLUGIN_LV2 && label != nullptr)
  440. {
  441. if (std::strncmp(label, "http://calf.sourceforge.net/plugins/", 36) == 0 ||
  442. std::strcmp(label, "http://factorial.hu/plugins/lv2/ir") == 0 ||
  443. std::strstr(label, "v1.sourceforge.net/lv2") != nullptr)
  444. {
  445. preferBridges = true;
  446. }
  447. }
  448. }
  449. #endif // ! BUILD_BRIDGE
  450. const bool canBeBridged = ptype != PLUGIN_INTERNAL
  451. && ptype != PLUGIN_SF2
  452. && ptype != PLUGIN_SFZ
  453. && ptype != PLUGIN_JACK;
  454. if (canBeBridged && (btype != BINARY_NATIVE || (preferBridges && bridgeBinary.isNotEmpty())))
  455. {
  456. if (bridgeBinary.isNotEmpty())
  457. {
  458. plugin = CarlaPlugin::newBridge(initializer, btype, ptype, bridgeBinary);
  459. }
  460. else
  461. {
  462. setLastError("This Carla build cannot handle this binary");
  463. return false;
  464. }
  465. }
  466. else
  467. {
  468. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  469. bool use16Outs;
  470. #endif
  471. setLastError("Invalid or unsupported plugin type");
  472. // Some stupid plugins mess up with global signals, err!!
  473. const CarlaSignalRestorer csr;
  474. switch (ptype)
  475. {
  476. case PLUGIN_NONE:
  477. break;
  478. case PLUGIN_LADSPA:
  479. plugin = CarlaPlugin::newLADSPA(initializer, (const LADSPA_RDF_Descriptor*)extra);
  480. break;
  481. case PLUGIN_DSSI:
  482. plugin = CarlaPlugin::newDSSI(initializer);
  483. break;
  484. case PLUGIN_LV2:
  485. plugin = CarlaPlugin::newLV2(initializer);
  486. break;
  487. case PLUGIN_VST2:
  488. plugin = CarlaPlugin::newVST2(initializer);
  489. break;
  490. case PLUGIN_VST3:
  491. plugin = CarlaPlugin::newVST3(initializer);
  492. break;
  493. case PLUGIN_AU:
  494. plugin = CarlaPlugin::newAU(initializer);
  495. break;
  496. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  497. case PLUGIN_INTERNAL:
  498. plugin = CarlaPlugin::newNative(initializer);
  499. break;
  500. case PLUGIN_DLS:
  501. case PLUGIN_GIG:
  502. case PLUGIN_SF2:
  503. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  504. plugin = CarlaPlugin::newFluidSynth(initializer, use16Outs);
  505. break;
  506. case PLUGIN_SFZ:
  507. plugin = CarlaPlugin::newSFZero(initializer);
  508. break;
  509. case PLUGIN_JACK:
  510. plugin = CarlaPlugin::newJackApp(initializer);
  511. break;
  512. #else
  513. case PLUGIN_INTERNAL:
  514. case PLUGIN_DLS:
  515. case PLUGIN_GIG:
  516. case PLUGIN_SF2:
  517. case PLUGIN_SFZ:
  518. case PLUGIN_JACK:
  519. setLastError("Plugin bridges cannot handle this binary");
  520. break;
  521. #endif
  522. }
  523. }
  524. if (plugin == nullptr)
  525. return false;
  526. plugin->reload();
  527. bool canRun = true;
  528. /**/ if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  529. {
  530. if (plugin->getCVInCount() > 0 || plugin->getCVInCount() > 0)
  531. {
  532. setLastError("Carla's rack mode cannot work with plugins that have CV ports, sorry!");
  533. canRun = false;
  534. }
  535. }
  536. else if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  537. {
  538. /**/ if (plugin->getMidiInCount() > 1 || plugin->getMidiOutCount() > 1)
  539. {
  540. setLastError("Carla's patchbay mode cannot work with plugins that have multiple MIDI ports, sorry!");
  541. canRun = false;
  542. }
  543. }
  544. if (! canRun)
  545. {
  546. delete plugin;
  547. return false;
  548. }
  549. EnginePluginData& pluginData(pData->plugins[id]);
  550. pluginData.plugin = plugin;
  551. carla_zeroFloats(pluginData.peaks, 4);
  552. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  553. if (oldPlugin != nullptr)
  554. {
  555. CARLA_SAFE_ASSERT(! pData->loadingProject);
  556. const ScopedThreadStopper sts(this);
  557. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  558. pData->graph.replacePlugin(oldPlugin, plugin);
  559. const bool wasActive = oldPlugin->getInternalParameterValue(PARAMETER_ACTIVE) >= 0.5f;
  560. const float oldDryWet = oldPlugin->getInternalParameterValue(PARAMETER_DRYWET);
  561. const float oldVolume = oldPlugin->getInternalParameterValue(PARAMETER_VOLUME);
  562. delete oldPlugin;
  563. if (plugin->getHints() & PLUGIN_CAN_DRYWET)
  564. plugin->setDryWet(oldDryWet, true, true);
  565. if (plugin->getHints() & PLUGIN_CAN_VOLUME)
  566. plugin->setVolume(oldVolume, true, true);
  567. plugin->setActive(wasActive, true, true);
  568. plugin->setEnabled(true);
  569. callback(true, true, ENGINE_CALLBACK_RELOAD_ALL, id, 0, 0, 0, 0.0f, nullptr);
  570. }
  571. else if (! pData->loadingProject)
  572. #endif
  573. {
  574. plugin->setEnabled(true);
  575. ++pData->curPluginCount;
  576. callback(true, true, ENGINE_CALLBACK_PLUGIN_ADDED, id, 0, 0, 0, 0.0f, plugin->getName());
  577. if (getType() != kEngineTypeBridge)
  578. plugin->setActive(true, true, true);
  579. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  580. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  581. pData->graph.addPlugin(plugin);
  582. #endif
  583. }
  584. return true;
  585. }
  586. bool CarlaEngine::addPlugin(const PluginType ptype,
  587. const char* const filename,
  588. const char* const name,
  589. const char* const label,
  590. const int64_t uniqueId,
  591. const void* const extra)
  592. {
  593. return addPlugin(BINARY_NATIVE, ptype, filename, name, label, uniqueId, extra, PLUGIN_OPTIONS_NULL);
  594. }
  595. bool CarlaEngine::removePlugin(const uint id)
  596. {
  597. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  598. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  599. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  600. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data");
  601. #endif
  602. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  603. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id");
  604. carla_debug("CarlaEngine::removePlugin(%i)", id);
  605. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  606. CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to remove");
  607. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data");
  608. const ScopedThreadStopper sts(this);
  609. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  610. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  611. pData->graph.removePlugin(plugin);
  612. const ScopedActionLock sal(this, kEnginePostActionRemovePlugin, id, 0);
  613. /*
  614. for (uint i=id; i < pData->curPluginCount; ++i)
  615. {
  616. CarlaPlugin* const plugin2(pData->plugins[i].plugin);
  617. CARLA_SAFE_ASSERT_BREAK(plugin2 != nullptr);
  618. plugin2->updateOscURL();
  619. }
  620. */
  621. #else
  622. pData->curPluginCount = 0;
  623. carla_zeroStructs(pData->plugins, 1);
  624. #endif
  625. delete plugin;
  626. callback(true, true, ENGINE_CALLBACK_PLUGIN_REMOVED, id, 0, 0, 0, 0.0f, nullptr);
  627. return true;
  628. }
  629. bool CarlaEngine::removeAllPlugins()
  630. {
  631. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  632. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  633. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  634. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextPluginId == pData->maxPluginNumber, "Invalid engine internal data");
  635. #endif
  636. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  637. carla_debug("CarlaEngine::removeAllPlugins()");
  638. if (pData->curPluginCount == 0)
  639. return true;
  640. const ScopedThreadStopper sts(this);
  641. const uint curPluginCount(pData->curPluginCount);
  642. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  643. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  644. pData->graph.removeAllPlugins();
  645. #endif
  646. const ScopedActionLock sal(this, kEnginePostActionZeroCount, 0, 0);
  647. callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  648. for (uint i=0; i < curPluginCount; ++i)
  649. {
  650. const uint id = curPluginCount - i - 1;
  651. EnginePluginData& pluginData(pData->plugins[id]);
  652. if (pluginData.plugin != nullptr)
  653. {
  654. delete pluginData.plugin;
  655. pluginData.plugin = nullptr;
  656. }
  657. carla_zeroFloats(pluginData.peaks, 4);
  658. callback(true, true, ENGINE_CALLBACK_PLUGIN_REMOVED, id, 0, 0, 0, 0.0f, nullptr);
  659. callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  660. }
  661. return true;
  662. }
  663. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  664. bool CarlaEngine::renamePlugin(const uint id, const char* const newName)
  665. {
  666. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  667. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  668. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data");
  669. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  670. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id");
  671. CARLA_SAFE_ASSERT_RETURN_ERR(newName != nullptr && newName[0] != '\0', "Invalid plugin name");
  672. carla_debug("CarlaEngine::renamePlugin(%i, \"%s\")", id, newName);
  673. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  674. CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to rename");
  675. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data");
  676. const char* const uniqueName(getUniquePluginName(newName));
  677. CARLA_SAFE_ASSERT_RETURN_ERR(uniqueName != nullptr, "Unable to get new unique plugin name");
  678. plugin->setName(uniqueName);
  679. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  680. pData->graph.renamePlugin(plugin, uniqueName);
  681. callback(true, true, ENGINE_CALLBACK_PLUGIN_RENAMED, id, 0, 0, 0, 0.0f, uniqueName);
  682. delete[] uniqueName;
  683. return true;
  684. }
  685. bool CarlaEngine::clonePlugin(const uint id)
  686. {
  687. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  688. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  689. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data");
  690. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  691. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id");
  692. carla_debug("CarlaEngine::clonePlugin(%i)", id);
  693. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  694. CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to clone");
  695. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data");
  696. char label[STR_MAX+1];
  697. carla_zeroChars(label, STR_MAX+1);
  698. if (! plugin->getLabel(label))
  699. label[0] = '\0';
  700. const uint pluginCountBefore(pData->curPluginCount);
  701. if (! addPlugin(plugin->getBinaryType(), plugin->getType(),
  702. plugin->getFilename(), plugin->getName(), label, plugin->getUniqueId(),
  703. plugin->getExtraStuff(), plugin->getOptionsEnabled()))
  704. return false;
  705. CARLA_SAFE_ASSERT_RETURN_ERR(pluginCountBefore+1 == pData->curPluginCount, "No new plugin found");
  706. if (CarlaPlugin* const newPlugin = pData->plugins[pluginCountBefore].plugin)
  707. newPlugin->loadStateSave(plugin->getStateSave());
  708. return true;
  709. }
  710. bool CarlaEngine::replacePlugin(const uint id) noexcept
  711. {
  712. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  713. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  714. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data");
  715. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  716. carla_debug("CarlaEngine::replacePlugin(%i)", id);
  717. // might use this to reset
  718. if (id == pData->maxPluginNumber)
  719. {
  720. pData->nextPluginId = pData->maxPluginNumber;
  721. return true;
  722. }
  723. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id");
  724. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  725. CARLA_SAFE_ASSERT_RETURN_ERR(plugin != nullptr, "Could not find plugin to replace");
  726. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data");
  727. pData->nextPluginId = id;
  728. return true;
  729. }
  730. bool CarlaEngine::switchPlugins(const uint idA, const uint idB) 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 >= 2, "Invalid engine internal data");
  735. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  736. CARLA_SAFE_ASSERT_RETURN_ERR(idA != idB, "Invalid operation, cannot switch plugin with itself");
  737. CARLA_SAFE_ASSERT_RETURN_ERR(idA < pData->curPluginCount, "Invalid plugin Id");
  738. CARLA_SAFE_ASSERT_RETURN_ERR(idB < pData->curPluginCount, "Invalid plugin Id");
  739. carla_debug("CarlaEngine::switchPlugins(%i)", idA, idB);
  740. CarlaPlugin* const pluginA(pData->plugins[idA].plugin);
  741. CarlaPlugin* const pluginB(pData->plugins[idB].plugin);
  742. CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch");
  743. CARLA_SAFE_ASSERT_RETURN_ERR(pluginA != nullptr, "Could not find plugin to switch");
  744. CARLA_SAFE_ASSERT_RETURN_ERR(pluginA->getId() == idA, "Invalid engine internal data");
  745. CARLA_SAFE_ASSERT_RETURN_ERR(pluginB->getId() == idB, "Invalid engine internal data");
  746. const ScopedThreadStopper sts(this);
  747. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  748. pData->graph.replacePlugin(pluginA, pluginB);
  749. const ScopedActionLock sal(this, kEnginePostActionSwitchPlugins, idA, idB);
  750. // TODO
  751. /*
  752. pluginA->updateOscURL();
  753. pluginB->updateOscURL();
  754. if (isOscControlRegistered())
  755. oscSend_control_switch_plugins(idA, idB);
  756. */
  757. return true;
  758. }
  759. #endif
  760. void CarlaEngine::touchPluginParameter(const uint, const uint32_t, const bool) noexcept
  761. {
  762. }
  763. CarlaPlugin* CarlaEngine::getPlugin(const uint id) const noexcept
  764. {
  765. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  766. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->plugins != nullptr, "Invalid engine internal data");
  767. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->curPluginCount != 0, "Invalid engine internal data");
  768. #endif
  769. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  770. CARLA_SAFE_ASSERT_RETURN_ERRN(id < pData->curPluginCount, "Invalid plugin Id");
  771. return pData->plugins[id].plugin;
  772. }
  773. CarlaPlugin* CarlaEngine::getPluginUnchecked(const uint id) const noexcept
  774. {
  775. return pData->plugins[id].plugin;
  776. }
  777. const char* CarlaEngine::getUniquePluginName(const char* const name) const
  778. {
  779. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull, nullptr);
  780. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr);
  781. carla_debug("CarlaEngine::getUniquePluginName(\"%s\")", name);
  782. CarlaString sname;
  783. sname = name;
  784. if (sname.isEmpty())
  785. {
  786. sname = "(No name)";
  787. return sname.dup();
  788. }
  789. const std::size_t maxNameSize(carla_minConstrained<uint>(getMaxClientNameSize(), 0xff, 6U) - 6); // 6 = strlen(" (10)") + 1
  790. if (maxNameSize == 0 || ! isRunning())
  791. return sname.dup();
  792. sname.truncate(maxNameSize);
  793. sname.replace(':', '.'); // ':' is used in JACK1 to split client/port names
  794. for (uint i=0; i < pData->curPluginCount; ++i)
  795. {
  796. CARLA_SAFE_ASSERT_BREAK(pData->plugins[i].plugin != nullptr);
  797. // Check if unique name doesn't exist
  798. if (const char* const pluginName = pData->plugins[i].plugin->getName())
  799. {
  800. if (sname != pluginName)
  801. continue;
  802. }
  803. // Check if string has already been modified
  804. {
  805. const std::size_t len(sname.length());
  806. // 1 digit, ex: " (2)"
  807. if (sname[len-4] == ' ' && sname[len-3] == '(' && sname.isDigit(len-2) && sname[len-1] == ')')
  808. {
  809. const int number = sname[len-2] - '0';
  810. if (number == 9)
  811. {
  812. // next number is 10, 2 digits
  813. sname.truncate(len-4);
  814. sname += " (10)";
  815. //sname.replace(" (9)", " (10)");
  816. }
  817. else
  818. sname[len-2] = char('0' + number + 1);
  819. continue;
  820. }
  821. // 2 digits, ex: " (11)"
  822. if (sname[len-5] == ' ' && sname[len-4] == '(' && sname.isDigit(len-3) && sname.isDigit(len-2) && sname[len-1] == ')')
  823. {
  824. char n2 = sname[len-2];
  825. char n3 = sname[len-3];
  826. if (n2 == '9')
  827. {
  828. n2 = '0';
  829. n3 = static_cast<char>(n3 + 1);
  830. }
  831. else
  832. n2 = static_cast<char>(n2 + 1);
  833. sname[len-2] = n2;
  834. sname[len-3] = n3;
  835. continue;
  836. }
  837. }
  838. // Modify string if not
  839. sname += " (2)";
  840. }
  841. return sname.dup();
  842. }
  843. // -----------------------------------------------------------------------
  844. // Project management
  845. bool CarlaEngine::loadFile(const char* const filename)
  846. {
  847. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  848. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename");
  849. carla_debug("CarlaEngine::loadFile(\"%s\")", filename);
  850. const String jfilename = String(CharPointer_UTF8(filename));
  851. File file(jfilename);
  852. CARLA_SAFE_ASSERT_RETURN_ERR(file.exists(), "Requested file does not exist or is not a readable");
  853. CarlaString baseName(file.getFileNameWithoutExtension().toRawUTF8());
  854. CarlaString extension(file.getFileExtension().replace(".","").toLowerCase().toRawUTF8());
  855. const uint curPluginId(pData->nextPluginId < pData->curPluginCount ? pData->nextPluginId : pData->curPluginCount);
  856. // -------------------------------------------------------------------
  857. // NOTE: please keep in sync with carla_get_supported_file_extensions!!
  858. if (extension == "carxp" || extension == "carxs")
  859. return loadProject(filename, false);
  860. // -------------------------------------------------------------------
  861. if (extension == "sf2" || extension == "sf3")
  862. return addPlugin(PLUGIN_SF2, filename, baseName, baseName, 0, nullptr);
  863. if (extension == "sfz")
  864. return addPlugin(PLUGIN_SFZ, filename, baseName, baseName, 0, nullptr);
  865. // -------------------------------------------------------------------
  866. if (
  867. #ifdef HAVE_SNDFILE
  868. extension == "aif" ||
  869. extension == "aifc" ||
  870. extension == "aiff" ||
  871. extension == "au" ||
  872. extension == "bwf" ||
  873. extension == "flac" ||
  874. extension == "htk" ||
  875. extension == "iff" ||
  876. extension == "mat4" ||
  877. extension == "mat5" ||
  878. extension == "oga" ||
  879. extension == "ogg" ||
  880. extension == "paf" ||
  881. extension == "pvf" ||
  882. extension == "pvf5" ||
  883. extension == "sd2" ||
  884. extension == "sf" ||
  885. extension == "snd" ||
  886. extension == "svx" ||
  887. extension == "vcc" ||
  888. extension == "w64" ||
  889. extension == "wav" ||
  890. extension == "xi" ||
  891. #endif
  892. #ifdef HAVE_FFMPEG
  893. extension == "3g2" ||
  894. extension == "3gp" ||
  895. extension == "aac" ||
  896. extension == "ac3" ||
  897. extension == "amr" ||
  898. extension == "ape" ||
  899. extension == "mp2" ||
  900. extension == "mp3" ||
  901. extension == "mpc" ||
  902. extension == "wma" ||
  903. # ifndef HAVE_SNDFILE
  904. // FFmpeg without sndfile
  905. extension == "flac" ||
  906. extension == "oga" ||
  907. extension == "ogg" ||
  908. extension == "w64" ||
  909. extension == "wav" ||
  910. # endif
  911. #endif
  912. false
  913. )
  914. {
  915. if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "audiofile", 0, nullptr))
  916. {
  917. if (CarlaPlugin* const plugin = getPlugin(curPluginId))
  918. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "file", filename, true);
  919. return true;
  920. }
  921. return false;
  922. }
  923. // -------------------------------------------------------------------
  924. if (extension == "mid" || extension == "midi")
  925. {
  926. if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "midifile", 0, nullptr))
  927. {
  928. if (CarlaPlugin* const plugin = getPlugin(curPluginId))
  929. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "file", filename, true);
  930. return true;
  931. }
  932. return false;
  933. }
  934. // -------------------------------------------------------------------
  935. // ZynAddSubFX
  936. if (extension == "xmz" || extension == "xiz")
  937. {
  938. #ifdef HAVE_ZYN_DEPS
  939. CarlaString nicerName("Zyn - ");
  940. const std::size_t sep(baseName.find('-')+1);
  941. if (sep < baseName.length())
  942. nicerName += baseName.buffer()+sep;
  943. else
  944. nicerName += baseName;
  945. //nicerName
  946. if (addPlugin(PLUGIN_INTERNAL, nullptr, nicerName, "zynaddsubfx", 0, nullptr))
  947. {
  948. callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, curPluginId, 0, 0, 0, 0.0f, nullptr);
  949. if (CarlaPlugin* const plugin = getPlugin(curPluginId))
  950. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, (extension == "xmz") ? "CarlaAlternateFile1" : "CarlaAlternateFile2", filename, true);
  951. return true;
  952. }
  953. return false;
  954. #else
  955. setLastError("This Carla build does not have ZynAddSubFX support");
  956. return false;
  957. #endif
  958. }
  959. // -------------------------------------------------------------------
  960. // Direct plugin binaries
  961. #ifdef CARLA_OS_MAC
  962. if (extension == "vst")
  963. return addPlugin(PLUGIN_VST2, filename, nullptr, nullptr, 0, nullptr);
  964. #else
  965. if (extension == "dll" || extension == "so")
  966. return addPlugin(getBinaryTypeFromFile(filename), PLUGIN_VST2, filename, nullptr, nullptr, 0, nullptr);
  967. #endif
  968. #if defined(USING_JUCE) && (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
  969. if (extension == "vst3")
  970. return addPlugin(getBinaryTypeFromFile(filename), PLUGIN_VST3, filename, nullptr, nullptr, 0, nullptr);
  971. #endif
  972. // -------------------------------------------------------------------
  973. setLastError("Unknown file extension");
  974. return false;
  975. }
  976. bool CarlaEngine::loadProject(const char* const filename, const bool setAsCurrentProject)
  977. {
  978. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  979. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename");
  980. carla_debug("CarlaEngine::loadProject(\"%s\")", filename);
  981. const String jfilename = String(CharPointer_UTF8(filename));
  982. File file(jfilename);
  983. CARLA_SAFE_ASSERT_RETURN_ERR(file.existsAsFile(), "Requested file does not exist or is not a readable file");
  984. if (setAsCurrentProject)
  985. {
  986. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  987. pData->currentProjectFilename = filename;
  988. #endif
  989. }
  990. XmlDocument xml(file);
  991. return loadProjectInternal(xml);
  992. }
  993. bool CarlaEngine::saveProject(const char* const filename, const bool setAsCurrentProject)
  994. {
  995. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename");
  996. carla_debug("CarlaEngine::saveProject(\"%s\")", filename);
  997. MemoryOutputStream out;
  998. saveProjectInternal(out);
  999. const String jfilename = String(CharPointer_UTF8(filename));
  1000. File file(jfilename);
  1001. if (setAsCurrentProject)
  1002. {
  1003. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1004. pData->currentProjectFilename = filename;
  1005. #endif
  1006. }
  1007. if (file.replaceWithData(out.getData(), out.getDataSize()))
  1008. return true;
  1009. setLastError("Failed to write file");
  1010. return false;
  1011. }
  1012. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1013. const char* CarlaEngine::getCurrentProjectFilename() const noexcept
  1014. {
  1015. return pData->currentProjectFilename;
  1016. }
  1017. void CarlaEngine::clearCurrentProjectFilename() noexcept
  1018. {
  1019. pData->currentProjectFilename.clear();
  1020. }
  1021. #endif
  1022. // -----------------------------------------------------------------------
  1023. // Information (base)
  1024. uint32_t CarlaEngine::getBufferSize() const noexcept
  1025. {
  1026. return pData->bufferSize;
  1027. }
  1028. double CarlaEngine::getSampleRate() const noexcept
  1029. {
  1030. return pData->sampleRate;
  1031. }
  1032. const char* CarlaEngine::getName() const noexcept
  1033. {
  1034. return pData->name;
  1035. }
  1036. EngineProcessMode CarlaEngine::getProccessMode() const noexcept
  1037. {
  1038. return pData->options.processMode;
  1039. }
  1040. const EngineOptions& CarlaEngine::getOptions() const noexcept
  1041. {
  1042. return pData->options;
  1043. }
  1044. EngineTimeInfo CarlaEngine::getTimeInfo() const noexcept
  1045. {
  1046. return pData->timeInfo;
  1047. }
  1048. // -----------------------------------------------------------------------
  1049. // Information (peaks)
  1050. const float* CarlaEngine::getPeaks(const uint pluginId) const noexcept
  1051. {
  1052. static const float kFallback[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  1053. if (pluginId == MAIN_CARLA_PLUGIN_ID)
  1054. {
  1055. // get peak from first plugin, if available
  1056. if (const uint count = pData->curPluginCount)
  1057. {
  1058. pData->peaks[0] = pData->plugins[0].peaks[0];
  1059. pData->peaks[1] = pData->plugins[0].peaks[1];
  1060. pData->peaks[2] = pData->plugins[count-1].peaks[2];
  1061. pData->peaks[3] = pData->plugins[count-1].peaks[3];
  1062. }
  1063. else
  1064. {
  1065. carla_zeroFloats(pData->peaks, 4);
  1066. }
  1067. return pData->peaks;
  1068. }
  1069. CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, kFallback);
  1070. return pData->plugins[pluginId].peaks;
  1071. }
  1072. float CarlaEngine::getInputPeak(const uint pluginId, const bool isLeft) const noexcept
  1073. {
  1074. if (pluginId == MAIN_CARLA_PLUGIN_ID)
  1075. {
  1076. // get peak from first plugin, if available
  1077. if (pData->curPluginCount > 0)
  1078. return pData->plugins[0].peaks[isLeft ? 0 : 1];
  1079. return 0.0f;
  1080. }
  1081. CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, 0.0f);
  1082. return pData->plugins[pluginId].peaks[isLeft ? 0 : 1];
  1083. }
  1084. float CarlaEngine::getOutputPeak(const uint pluginId, const bool isLeft) const noexcept
  1085. {
  1086. if (pluginId == MAIN_CARLA_PLUGIN_ID)
  1087. {
  1088. // get peak from last plugin, if available
  1089. if (pData->curPluginCount > 0)
  1090. return pData->plugins[pData->curPluginCount-1].peaks[isLeft ? 2 : 3];
  1091. return 0.0f;
  1092. }
  1093. CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, 0.0f);
  1094. return pData->plugins[pluginId].peaks[isLeft ? 2 : 3];
  1095. }
  1096. // -----------------------------------------------------------------------
  1097. // Callback
  1098. void CarlaEngine::callback(const bool sendHost, const bool sendOsc,
  1099. const EngineCallbackOpcode action, const uint pluginId,
  1100. const int value1, const int value2, const int value3,
  1101. const float valuef, const char* const valueStr) noexcept
  1102. {
  1103. #ifdef DEBUG
  1104. if (pData->isIdling)
  1105. carla_stdout("CarlaEngine::callback [while idling] (%i:%s, %i, %i, %i, %i, %f, \"%s\")",
  1106. action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3,
  1107. static_cast<double>(valuef), valueStr);
  1108. else if (action != ENGINE_CALLBACK_IDLE && action != ENGINE_CALLBACK_NOTE_ON && action != ENGINE_CALLBACK_NOTE_OFF)
  1109. carla_debug("CarlaEngine::callback(%i:%s, %i, %i, %i, %i, %f, \"%s\")",
  1110. action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3,
  1111. static_cast<double>(valuef), valueStr);
  1112. #endif
  1113. if (sendHost && pData->callback != nullptr)
  1114. {
  1115. if (action == ENGINE_CALLBACK_IDLE)
  1116. ++pData->isIdling;
  1117. try {
  1118. pData->callback(pData->callbackPtr, action, pluginId, value1, value2, value3, valuef, valueStr);
  1119. #if defined(CARLA_OS_LINUX) && defined(__arm__)
  1120. } catch (__cxxabiv1::__forced_unwind&) {
  1121. carla_stderr2("Caught forced unwind exception in callback");
  1122. throw;
  1123. #endif
  1124. } catch (...) {
  1125. carla_safe_exception("callback", __FILE__, __LINE__);
  1126. }
  1127. if (action == ENGINE_CALLBACK_IDLE)
  1128. --pData->isIdling;
  1129. }
  1130. if (sendOsc)
  1131. {
  1132. #if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE)
  1133. if (pData->osc.isControlRegisteredForTCP())
  1134. {
  1135. switch (action)
  1136. {
  1137. case ENGINE_CALLBACK_RELOAD_INFO:
  1138. {
  1139. CarlaPlugin* const plugin = pData->plugins[pluginId].plugin;
  1140. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  1141. pData->osc.sendPluginInfo(plugin);
  1142. break;
  1143. }
  1144. case ENGINE_CALLBACK_RELOAD_PARAMETERS:
  1145. {
  1146. CarlaPlugin* const plugin = pData->plugins[pluginId].plugin;
  1147. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  1148. pData->osc.sendPluginPortCount(plugin);
  1149. if (const uint32_t count = plugin->getParameterCount())
  1150. {
  1151. for (uint32_t i=0; i<count; ++i)
  1152. pData->osc.sendPluginParameterInfo(plugin, i);
  1153. }
  1154. break;
  1155. }
  1156. case ENGINE_CALLBACK_RELOAD_PROGRAMS:
  1157. {
  1158. CarlaPlugin* const plugin = pData->plugins[pluginId].plugin;
  1159. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  1160. pData->osc.sendPluginProgramCount(plugin);
  1161. if (const uint32_t count = plugin->getProgramCount())
  1162. {
  1163. for (uint32_t i=0; i<count; ++i)
  1164. pData->osc.sendPluginProgram(plugin, i);
  1165. }
  1166. if (const uint32_t count = plugin->getMidiProgramCount())
  1167. {
  1168. for (uint32_t i=0; i<count; ++i)
  1169. pData->osc.sendPluginMidiProgram(plugin, i);
  1170. }
  1171. break;
  1172. }
  1173. case ENGINE_CALLBACK_PLUGIN_ADDED:
  1174. case ENGINE_CALLBACK_RELOAD_ALL:
  1175. {
  1176. CarlaPlugin* const plugin = pData->plugins[pluginId].plugin;
  1177. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  1178. pData->osc.sendPluginInfo(plugin);
  1179. pData->osc.sendPluginPortCount(plugin);
  1180. pData->osc.sendPluginDataCount(plugin);
  1181. if (const uint32_t count = plugin->getParameterCount())
  1182. {
  1183. for (uint32_t i=0; i<count; ++i)
  1184. pData->osc.sendPluginParameterInfo(plugin, i);
  1185. }
  1186. if (const uint32_t count = plugin->getProgramCount())
  1187. {
  1188. for (uint32_t i=0; i<count; ++i)
  1189. pData->osc.sendPluginProgram(plugin, i);
  1190. }
  1191. if (const uint32_t count = plugin->getMidiProgramCount())
  1192. {
  1193. for (uint32_t i=0; i<count; ++i)
  1194. pData->osc.sendPluginMidiProgram(plugin, i);
  1195. }
  1196. if (const uint32_t count = plugin->getCustomDataCount())
  1197. {
  1198. for (uint32_t i=0; i<count; ++i)
  1199. pData->osc.sendPluginCustomData(plugin, i);
  1200. }
  1201. pData->osc.sendPluginInternalParameterValues(plugin);
  1202. break;
  1203. }
  1204. case ENGINE_CALLBACK_IDLE:
  1205. return;
  1206. default:
  1207. break;
  1208. }
  1209. pData->osc.sendCallback(action, pluginId, value1, value2, value3, valuef, valueStr);
  1210. }
  1211. #endif
  1212. }
  1213. }
  1214. void CarlaEngine::setCallback(const EngineCallbackFunc func, void* const ptr) noexcept
  1215. {
  1216. carla_debug("CarlaEngine::setCallback(%p, %p)", func, ptr);
  1217. pData->callback = func;
  1218. pData->callbackPtr = ptr;
  1219. }
  1220. // -----------------------------------------------------------------------
  1221. // File Callback
  1222. const char* CarlaEngine::runFileCallback(const FileCallbackOpcode action, const bool isDir, const char* const title, const char* const filter) noexcept
  1223. {
  1224. CARLA_SAFE_ASSERT_RETURN(title != nullptr && title[0] != '\0', nullptr);
  1225. CARLA_SAFE_ASSERT_RETURN(filter != nullptr, nullptr);
  1226. carla_debug("CarlaEngine::runFileCallback(%i:%s, %s, \"%s\", \"%s\")", action, FileCallbackOpcode2Str(action), bool2str(isDir), title, filter);
  1227. const char* ret = nullptr;
  1228. if (pData->fileCallback != nullptr)
  1229. {
  1230. try {
  1231. ret = pData->fileCallback(pData->fileCallbackPtr, action, isDir, title, filter);
  1232. } CARLA_SAFE_EXCEPTION("runFileCallback");
  1233. }
  1234. return ret;
  1235. }
  1236. void CarlaEngine::setFileCallback(const FileCallbackFunc func, void* const ptr) noexcept
  1237. {
  1238. carla_debug("CarlaEngine::setFileCallback(%p, %p)", func, ptr);
  1239. pData->fileCallback = func;
  1240. pData->fileCallbackPtr = ptr;
  1241. }
  1242. // -----------------------------------------------------------------------
  1243. // Transport
  1244. void CarlaEngine::transportPlay() noexcept
  1245. {
  1246. pData->timeInfo.playing = true;
  1247. pData->time.setNeedsReset();
  1248. }
  1249. void CarlaEngine::transportPause() noexcept
  1250. {
  1251. if (pData->timeInfo.playing)
  1252. pData->time.pause();
  1253. else
  1254. pData->time.setNeedsReset();
  1255. }
  1256. void CarlaEngine::transportBPM(const double bpm) noexcept
  1257. {
  1258. CARLA_SAFE_ASSERT_RETURN(bpm >= 20.0,)
  1259. try {
  1260. pData->time.setBPM(bpm);
  1261. } CARLA_SAFE_EXCEPTION("CarlaEngine::transportBPM");
  1262. }
  1263. void CarlaEngine::transportRelocate(const uint64_t frame) noexcept
  1264. {
  1265. pData->time.relocate(frame);
  1266. }
  1267. // -----------------------------------------------------------------------
  1268. // Error handling
  1269. const char* CarlaEngine::getLastError() const noexcept
  1270. {
  1271. return pData->lastError;
  1272. }
  1273. void CarlaEngine::setLastError(const char* const error) const noexcept
  1274. {
  1275. pData->lastError = error;
  1276. }
  1277. // -----------------------------------------------------------------------
  1278. // Misc
  1279. bool CarlaEngine::isAboutToClose() const noexcept
  1280. {
  1281. return pData->aboutToClose;
  1282. }
  1283. bool CarlaEngine::setAboutToClose() noexcept
  1284. {
  1285. carla_debug("CarlaEngine::setAboutToClose()");
  1286. pData->aboutToClose = true;
  1287. return (pData->isIdling == 0);
  1288. }
  1289. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1290. bool CarlaEngine::isLoadingProject() const noexcept
  1291. {
  1292. return pData->loadingProject;
  1293. }
  1294. #endif
  1295. void CarlaEngine::setActionCanceled(const bool canceled) noexcept
  1296. {
  1297. pData->actionCanceled = canceled;
  1298. }
  1299. bool CarlaEngine::wasActionCanceled() const noexcept
  1300. {
  1301. return pData->actionCanceled;
  1302. }
  1303. // -----------------------------------------------------------------------
  1304. // Global options
  1305. void CarlaEngine::setOption(const EngineOption option, const int value, const char* const valueStr) noexcept
  1306. {
  1307. carla_debug("CarlaEngine::setOption(%i:%s, %i, \"%s\")", option, EngineOption2Str(option), value, valueStr);
  1308. if (isRunning())
  1309. {
  1310. switch (option)
  1311. {
  1312. case ENGINE_OPTION_PROCESS_MODE:
  1313. case ENGINE_OPTION_AUDIO_TRIPLE_BUFFER:
  1314. case ENGINE_OPTION_AUDIO_DRIVER:
  1315. case ENGINE_OPTION_AUDIO_DEVICE:
  1316. return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Cannot set this option while engine is running!",
  1317. option, EngineOption2Str(option), value, valueStr);
  1318. default:
  1319. break;
  1320. }
  1321. }
  1322. // do not un-force stereo for rack mode
  1323. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && option == ENGINE_OPTION_FORCE_STEREO && value != 0)
  1324. return;
  1325. switch (option)
  1326. {
  1327. case ENGINE_OPTION_DEBUG:
  1328. break;
  1329. case ENGINE_OPTION_PROCESS_MODE:
  1330. CARLA_SAFE_ASSERT_RETURN(value >= ENGINE_PROCESS_MODE_SINGLE_CLIENT && value <= ENGINE_PROCESS_MODE_BRIDGE,);
  1331. pData->options.processMode = static_cast<EngineProcessMode>(value);
  1332. break;
  1333. case ENGINE_OPTION_TRANSPORT_MODE:
  1334. CARLA_SAFE_ASSERT_RETURN(value >= ENGINE_TRANSPORT_MODE_DISABLED && value <= ENGINE_TRANSPORT_MODE_BRIDGE,);
  1335. CARLA_SAFE_ASSERT_RETURN(getType() == kEngineTypeJack || value != ENGINE_TRANSPORT_MODE_JACK,);
  1336. pData->options.transportMode = static_cast<EngineTransportMode>(value);
  1337. delete[] pData->options.transportExtra;
  1338. if (value >= ENGINE_TRANSPORT_MODE_DISABLED && valueStr != nullptr)
  1339. pData->options.transportExtra = carla_strdup_safe(valueStr);
  1340. else
  1341. pData->options.transportExtra = nullptr;
  1342. pData->time.setNeedsReset();
  1343. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  1344. // enable link now if needed
  1345. {
  1346. const bool linkEnabled = pData->options.transportExtra != nullptr && std::strstr(pData->options.transportExtra, ":link:") != nullptr;
  1347. pData->time.enableLink(linkEnabled);
  1348. }
  1349. #endif
  1350. break;
  1351. case ENGINE_OPTION_FORCE_STEREO:
  1352. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1353. pData->options.forceStereo = (value != 0);
  1354. break;
  1355. case ENGINE_OPTION_PREFER_PLUGIN_BRIDGES:
  1356. #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1357. CARLA_SAFE_ASSERT_RETURN(value == 0,);
  1358. #else
  1359. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1360. #endif
  1361. pData->options.preferPluginBridges = (value != 0);
  1362. break;
  1363. case ENGINE_OPTION_PREFER_UI_BRIDGES:
  1364. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1365. pData->options.preferUiBridges = (value != 0);
  1366. break;
  1367. case ENGINE_OPTION_UIS_ALWAYS_ON_TOP:
  1368. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1369. pData->options.uisAlwaysOnTop = (value != 0);
  1370. break;
  1371. case ENGINE_OPTION_MAX_PARAMETERS:
  1372. CARLA_SAFE_ASSERT_RETURN(value >= 0,);
  1373. pData->options.maxParameters = static_cast<uint>(value);
  1374. break;
  1375. case ENGINE_OPTION_UI_BRIDGES_TIMEOUT:
  1376. CARLA_SAFE_ASSERT_RETURN(value >= 0,);
  1377. pData->options.uiBridgesTimeout = static_cast<uint>(value);
  1378. break;
  1379. case ENGINE_OPTION_AUDIO_BUFFER_SIZE:
  1380. CARLA_SAFE_ASSERT_RETURN(value >= 8,);
  1381. pData->options.audioBufferSize = static_cast<uint>(value);
  1382. break;
  1383. case ENGINE_OPTION_AUDIO_SAMPLE_RATE:
  1384. CARLA_SAFE_ASSERT_RETURN(value >= 22050,);
  1385. pData->options.audioSampleRate = static_cast<uint>(value);
  1386. break;
  1387. case ENGINE_OPTION_AUDIO_TRIPLE_BUFFER:
  1388. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1389. pData->options.audioTripleBuffer = (value != 0);
  1390. break;
  1391. case ENGINE_OPTION_AUDIO_DRIVER:
  1392. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,);
  1393. if (pData->options.audioDriver != nullptr)
  1394. delete[] pData->options.audioDriver;
  1395. pData->options.audioDriver = carla_strdup_safe(valueStr);
  1396. break;
  1397. case ENGINE_OPTION_AUDIO_DEVICE:
  1398. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,);
  1399. if (pData->options.audioDevice != nullptr)
  1400. delete[] pData->options.audioDevice;
  1401. pData->options.audioDevice = carla_strdup_safe(valueStr);
  1402. break;
  1403. case ENGINE_OPTION_OSC_ENABLED:
  1404. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1405. #ifndef BUILD_BRIDGE
  1406. pData->options.oscEnabled = (value != 0);
  1407. #endif
  1408. break;
  1409. case ENGINE_OPTION_OSC_PORT_TCP:
  1410. CARLA_SAFE_ASSERT_RETURN(value <= 0 || value >= 1024,);
  1411. #ifndef BUILD_BRIDGE
  1412. pData->options.oscPortTCP = value;
  1413. #endif
  1414. break;
  1415. case ENGINE_OPTION_OSC_PORT_UDP:
  1416. CARLA_SAFE_ASSERT_RETURN(value <= 0 || value >= 1024,);
  1417. #ifndef BUILD_BRIDGE
  1418. pData->options.oscPortUDP = value;
  1419. #endif
  1420. break;
  1421. case ENGINE_OPTION_FILE_PATH:
  1422. CARLA_SAFE_ASSERT_RETURN(value > FILE_NONE,);
  1423. CARLA_SAFE_ASSERT_RETURN(value <= FILE_MIDI,);
  1424. switch (value)
  1425. {
  1426. case FILE_AUDIO:
  1427. if (pData->options.pathAudio != nullptr)
  1428. delete[] pData->options.pathAudio;
  1429. if (valueStr != nullptr)
  1430. pData->options.pathAudio = carla_strdup_safe(valueStr);
  1431. else
  1432. pData->options.pathAudio = nullptr;
  1433. break;
  1434. case FILE_MIDI:
  1435. if (pData->options.pathMIDI != nullptr)
  1436. delete[] pData->options.pathMIDI;
  1437. if (valueStr != nullptr)
  1438. pData->options.pathMIDI = carla_strdup_safe(valueStr);
  1439. else
  1440. pData->options.pathMIDI = nullptr;
  1441. break;
  1442. default:
  1443. return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Invalid file type",
  1444. option, EngineOption2Str(option), value, valueStr);
  1445. break;
  1446. }
  1447. break;
  1448. case ENGINE_OPTION_PLUGIN_PATH:
  1449. CARLA_SAFE_ASSERT_RETURN(value > PLUGIN_NONE,);
  1450. CARLA_SAFE_ASSERT_RETURN(value <= PLUGIN_SFZ,);
  1451. switch (value)
  1452. {
  1453. case PLUGIN_LADSPA:
  1454. if (pData->options.pathLADSPA != nullptr)
  1455. delete[] pData->options.pathLADSPA;
  1456. if (valueStr != nullptr)
  1457. pData->options.pathLADSPA = carla_strdup_safe(valueStr);
  1458. else
  1459. pData->options.pathLADSPA = nullptr;
  1460. break;
  1461. case PLUGIN_DSSI:
  1462. if (pData->options.pathDSSI != nullptr)
  1463. delete[] pData->options.pathDSSI;
  1464. if (valueStr != nullptr)
  1465. pData->options.pathDSSI = carla_strdup_safe(valueStr);
  1466. else
  1467. pData->options.pathDSSI = nullptr;
  1468. break;
  1469. case PLUGIN_LV2:
  1470. if (pData->options.pathLV2 != nullptr)
  1471. delete[] pData->options.pathLV2;
  1472. if (valueStr != nullptr)
  1473. pData->options.pathLV2 = carla_strdup_safe(valueStr);
  1474. else
  1475. pData->options.pathLV2 = nullptr;
  1476. break;
  1477. case PLUGIN_VST2:
  1478. if (pData->options.pathVST2 != nullptr)
  1479. delete[] pData->options.pathVST2;
  1480. if (valueStr != nullptr)
  1481. pData->options.pathVST2 = carla_strdup_safe(valueStr);
  1482. else
  1483. pData->options.pathVST2 = nullptr;
  1484. break;
  1485. case PLUGIN_VST3:
  1486. if (pData->options.pathVST3 != nullptr)
  1487. delete[] pData->options.pathVST3;
  1488. if (valueStr != nullptr)
  1489. pData->options.pathVST3 = carla_strdup_safe(valueStr);
  1490. else
  1491. pData->options.pathVST3 = nullptr;
  1492. break;
  1493. case PLUGIN_SF2:
  1494. if (pData->options.pathSF2 != nullptr)
  1495. delete[] pData->options.pathSF2;
  1496. if (valueStr != nullptr)
  1497. pData->options.pathSF2 = carla_strdup_safe(valueStr);
  1498. else
  1499. pData->options.pathSF2 = nullptr;
  1500. break;
  1501. case PLUGIN_SFZ:
  1502. if (pData->options.pathSFZ != nullptr)
  1503. delete[] pData->options.pathSFZ;
  1504. if (valueStr != nullptr)
  1505. pData->options.pathSFZ = carla_strdup_safe(valueStr);
  1506. else
  1507. pData->options.pathSFZ = nullptr;
  1508. break;
  1509. default:
  1510. return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Invalid plugin type",
  1511. option, EngineOption2Str(option), value, valueStr);
  1512. break;
  1513. }
  1514. break;
  1515. case ENGINE_OPTION_PATH_BINARIES:
  1516. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1517. if (pData->options.binaryDir != nullptr)
  1518. delete[] pData->options.binaryDir;
  1519. pData->options.binaryDir = carla_strdup_safe(valueStr);
  1520. break;
  1521. case ENGINE_OPTION_PATH_RESOURCES:
  1522. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1523. if (pData->options.resourceDir != nullptr)
  1524. delete[] pData->options.resourceDir;
  1525. pData->options.resourceDir = carla_strdup_safe(valueStr);
  1526. break;
  1527. case ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR: {
  1528. CARLA_SAFE_ASSERT_RETURN(pData->options.binaryDir != nullptr && pData->options.binaryDir[0] != '\0',);
  1529. #ifdef CARLA_OS_LINUX
  1530. const ScopedEngineEnvironmentLocker _seel(this);
  1531. if (value != 0)
  1532. {
  1533. CarlaString interposerPath(CarlaString(pData->options.binaryDir) + "/libcarla_interposer-safe.so");
  1534. ::setenv("LD_PRELOAD", interposerPath.buffer(), 1);
  1535. }
  1536. else
  1537. {
  1538. ::unsetenv("LD_PRELOAD");
  1539. }
  1540. #endif
  1541. } break;
  1542. case ENGINE_OPTION_FRONTEND_UI_SCALE:
  1543. CARLA_SAFE_ASSERT_RETURN(value > 0,);
  1544. pData->options.uiScale = static_cast<float>(value) / 1000;
  1545. break;
  1546. case ENGINE_OPTION_FRONTEND_WIN_ID: {
  1547. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1548. const long long winId(std::strtoll(valueStr, nullptr, 16));
  1549. CARLA_SAFE_ASSERT_RETURN(winId >= 0,);
  1550. pData->options.frontendWinId = static_cast<uintptr_t>(winId);
  1551. } break;
  1552. #if !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) && !defined(CARLA_OS_WIN)
  1553. case ENGINE_OPTION_WINE_EXECUTABLE:
  1554. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1555. if (pData->options.wine.executable != nullptr)
  1556. delete[] pData->options.wine.executable;
  1557. pData->options.wine.executable = carla_strdup_safe(valueStr);
  1558. break;
  1559. case ENGINE_OPTION_WINE_AUTO_PREFIX:
  1560. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1561. pData->options.wine.autoPrefix = (value != 0);
  1562. break;
  1563. case ENGINE_OPTION_WINE_FALLBACK_PREFIX:
  1564. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1565. if (pData->options.wine.fallbackPrefix != nullptr)
  1566. delete[] pData->options.wine.fallbackPrefix;
  1567. pData->options.wine.fallbackPrefix = carla_strdup_safe(valueStr);
  1568. break;
  1569. case ENGINE_OPTION_WINE_RT_PRIO_ENABLED:
  1570. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1571. pData->options.wine.rtPrio = (value != 0);
  1572. break;
  1573. case ENGINE_OPTION_WINE_BASE_RT_PRIO:
  1574. CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 89,);
  1575. pData->options.wine.baseRtPrio = value;
  1576. break;
  1577. case ENGINE_OPTION_WINE_SERVER_RT_PRIO:
  1578. CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 99,);
  1579. pData->options.wine.serverRtPrio = value;
  1580. break;
  1581. #endif
  1582. case ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT:
  1583. break;
  1584. }
  1585. }
  1586. #ifndef BUILD_BRIDGE
  1587. // -----------------------------------------------------------------------
  1588. // OSC Stuff
  1589. bool CarlaEngine::isOscControlRegistered() const noexcept
  1590. {
  1591. # ifdef HAVE_LIBLO
  1592. return pData->osc.isControlRegisteredForTCP();
  1593. # else
  1594. return false;
  1595. # endif
  1596. }
  1597. const char* CarlaEngine::getOscServerPathTCP() const noexcept
  1598. {
  1599. # ifdef HAVE_LIBLO
  1600. return pData->osc.getServerPathTCP();
  1601. # else
  1602. return nullptr;
  1603. # endif
  1604. }
  1605. const char* CarlaEngine::getOscServerPathUDP() const noexcept
  1606. {
  1607. # ifdef HAVE_LIBLO
  1608. return pData->osc.getServerPathUDP();
  1609. # else
  1610. return nullptr;
  1611. # endif
  1612. }
  1613. #endif
  1614. // -----------------------------------------------------------------------
  1615. // Helper functions
  1616. EngineEvent* CarlaEngine::getInternalEventBuffer(const bool isInput) const noexcept
  1617. {
  1618. return isInput ? pData->events.in : pData->events.out;
  1619. }
  1620. // -----------------------------------------------------------------------
  1621. // Internal stuff
  1622. void CarlaEngine::bufferSizeChanged(const uint32_t newBufferSize)
  1623. {
  1624. carla_debug("CarlaEngine::bufferSizeChanged(%i)", newBufferSize);
  1625. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1626. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK ||
  1627. pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  1628. {
  1629. pData->graph.setBufferSize(newBufferSize);
  1630. }
  1631. #endif
  1632. pData->time.updateAudioValues(newBufferSize, pData->sampleRate);
  1633. for (uint i=0; i < pData->curPluginCount; ++i)
  1634. {
  1635. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1636. if (plugin != nullptr && plugin->isEnabled())
  1637. {
  1638. plugin->tryLock(true);
  1639. plugin->bufferSizeChanged(newBufferSize);
  1640. plugin->unlock();
  1641. }
  1642. }
  1643. callback(true, true, ENGINE_CALLBACK_BUFFER_SIZE_CHANGED, 0, static_cast<int>(newBufferSize), 0, 0, 0.0f, nullptr);
  1644. }
  1645. void CarlaEngine::sampleRateChanged(const double newSampleRate)
  1646. {
  1647. carla_debug("CarlaEngine::sampleRateChanged(%g)", newSampleRate);
  1648. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1649. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK ||
  1650. pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  1651. {
  1652. pData->graph.setSampleRate(newSampleRate);
  1653. }
  1654. #endif
  1655. pData->time.updateAudioValues(pData->bufferSize, newSampleRate);
  1656. for (uint i=0; i < pData->curPluginCount; ++i)
  1657. {
  1658. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1659. if (plugin != nullptr && plugin->isEnabled())
  1660. {
  1661. plugin->tryLock(true);
  1662. plugin->sampleRateChanged(newSampleRate);
  1663. plugin->unlock();
  1664. }
  1665. }
  1666. callback(true, true, ENGINE_CALLBACK_SAMPLE_RATE_CHANGED, 0, 0, 0, 0, static_cast<float>(newSampleRate), nullptr);
  1667. }
  1668. void CarlaEngine::offlineModeChanged(const bool isOfflineNow)
  1669. {
  1670. carla_debug("CarlaEngine::offlineModeChanged(%s)", bool2str(isOfflineNow));
  1671. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1672. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK ||
  1673. pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  1674. {
  1675. pData->graph.setOffline(isOfflineNow);
  1676. }
  1677. #endif
  1678. for (uint i=0; i < pData->curPluginCount; ++i)
  1679. {
  1680. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1681. if (plugin != nullptr && plugin->isEnabled())
  1682. plugin->offlineModeChanged(isOfflineNow);
  1683. }
  1684. }
  1685. void CarlaEngine::setPluginPeaksRT(const uint pluginId, float const inPeaks[2], float const outPeaks[2]) noexcept
  1686. {
  1687. EnginePluginData& pluginData(pData->plugins[pluginId]);
  1688. pluginData.peaks[0] = inPeaks[0];
  1689. pluginData.peaks[1] = inPeaks[1];
  1690. pluginData.peaks[2] = outPeaks[0];
  1691. pluginData.peaks[3] = outPeaks[1];
  1692. }
  1693. void CarlaEngine::saveProjectInternal(water::MemoryOutputStream& outStream) const
  1694. {
  1695. // send initial prepareForSave first, giving time for bridges to act
  1696. for (uint i=0; i < pData->curPluginCount; ++i)
  1697. {
  1698. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1699. if (plugin != nullptr && plugin->isEnabled())
  1700. {
  1701. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1702. // deactivate bridge client-side ping check, since some plugins block during save
  1703. if (plugin->getHints() & PLUGIN_IS_BRIDGE)
  1704. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "false", false);
  1705. #endif
  1706. plugin->prepareForSave();
  1707. }
  1708. }
  1709. outStream << "<?xml version='1.0' encoding='UTF-8'?>\n";
  1710. outStream << "<!DOCTYPE CARLA-PROJECT>\n";
  1711. outStream << "<CARLA-PROJECT VERSION='2.0'>\n";
  1712. const bool isPlugin(getType() == kEngineTypePlugin);
  1713. const EngineOptions& options(pData->options);
  1714. {
  1715. MemoryOutputStream outSettings(1024);
  1716. outSettings << " <EngineSettings>\n";
  1717. outSettings << " <ForceStereo>" << bool2str(options.forceStereo) << "</ForceStereo>\n";
  1718. outSettings << " <PreferPluginBridges>" << bool2str(options.preferPluginBridges) << "</PreferPluginBridges>\n";
  1719. outSettings << " <PreferUiBridges>" << bool2str(options.preferUiBridges) << "</PreferUiBridges>\n";
  1720. outSettings << " <UIsAlwaysOnTop>" << bool2str(options.uisAlwaysOnTop) << "</UIsAlwaysOnTop>\n";
  1721. outSettings << " <MaxParameters>" << String(options.maxParameters) << "</MaxParameters>\n";
  1722. outSettings << " <UIBridgesTimeout>" << String(options.uiBridgesTimeout) << "</UIBridgesTimeout>\n";
  1723. if (isPlugin)
  1724. {
  1725. outSettings << " <LADSPA_PATH>" << xmlSafeString(options.pathLADSPA, true) << "</LADSPA_PATH>\n";
  1726. outSettings << " <DSSI_PATH>" << xmlSafeString(options.pathDSSI, true) << "</DSSI_PATH>\n";
  1727. outSettings << " <LV2_PATH>" << xmlSafeString(options.pathLV2, true) << "</LV2_PATH>\n";
  1728. outSettings << " <VST2_PATH>" << xmlSafeString(options.pathVST2, true) << "</VST2_PATH>\n";
  1729. outSettings << " <VST3_PATH>" << xmlSafeString(options.pathVST3, true) << "</VST3_PATH>\n";
  1730. outSettings << " <SF2_PATH>" << xmlSafeString(options.pathSF2, true) << "</SF2_PATH>\n";
  1731. outSettings << " <SFZ_PATH>" << xmlSafeString(options.pathSFZ, true) << "</SFZ_PATH>\n";
  1732. }
  1733. outSettings << " </EngineSettings>\n";
  1734. outStream << outSettings;
  1735. }
  1736. if (pData->timeInfo.bbt.valid && ! isPlugin)
  1737. {
  1738. MemoryOutputStream outTransport(128);
  1739. outTransport << "\n <Transport>\n";
  1740. // outTransport << " <BeatsPerBar>" << pData->timeInfo.bbt.beatsPerBar << "</BeatsPerBar>\n";
  1741. outTransport << " <BeatsPerMinute>" << pData->timeInfo.bbt.beatsPerMinute << "</BeatsPerMinute>\n";
  1742. outTransport << " </Transport>\n";
  1743. outStream << outTransport;
  1744. }
  1745. char strBuf[STR_MAX+1];
  1746. carla_zeroChars(strBuf, STR_MAX+1);
  1747. for (uint i=0; i < pData->curPluginCount; ++i)
  1748. {
  1749. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1750. if (plugin != nullptr && plugin->isEnabled())
  1751. {
  1752. MemoryOutputStream outPlugin(4096), streamPlugin;
  1753. plugin->getStateSave(false).dumpToMemoryStream(streamPlugin);
  1754. outPlugin << "\n";
  1755. if (plugin->getRealName(strBuf))
  1756. outPlugin << " <!-- " << xmlSafeString(strBuf, true) << " -->\n";
  1757. outPlugin << " <Plugin>\n";
  1758. outPlugin << streamPlugin;
  1759. outPlugin << " </Plugin>\n";
  1760. outStream << outPlugin;
  1761. }
  1762. }
  1763. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1764. // tell bridges we're done saving
  1765. for (uint i=0; i < pData->curPluginCount; ++i)
  1766. {
  1767. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1768. if (plugin != nullptr && plugin->isEnabled() && (plugin->getHints() & PLUGIN_IS_BRIDGE) != 0)
  1769. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "true", false);
  1770. }
  1771. // save internal connections
  1772. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  1773. {
  1774. if (const char* const* const patchbayConns = getPatchbayConnections(false))
  1775. {
  1776. MemoryOutputStream outPatchbay(2048);
  1777. outPatchbay << "\n <Patchbay>\n";
  1778. for (int i=0; patchbayConns[i] != nullptr && patchbayConns[i+1] != nullptr; ++i, ++i )
  1779. {
  1780. const char* const connSource(patchbayConns[i]);
  1781. const char* const connTarget(patchbayConns[i+1]);
  1782. CARLA_SAFE_ASSERT_CONTINUE(connSource != nullptr && connSource[0] != '\0');
  1783. CARLA_SAFE_ASSERT_CONTINUE(connTarget != nullptr && connTarget[0] != '\0');
  1784. outPatchbay << " <Connection>\n";
  1785. outPatchbay << " <Source>" << xmlSafeString(connSource, true) << "</Source>\n";
  1786. outPatchbay << " <Target>" << xmlSafeString(connTarget, true) << "</Target>\n";
  1787. outPatchbay << " </Connection>\n";
  1788. }
  1789. outPatchbay << " </Patchbay>\n";
  1790. outStream << outPatchbay;
  1791. }
  1792. }
  1793. // if we're running inside some session-manager (and using JACK), let them handle the connections
  1794. bool saveExternalConnections;
  1795. /**/ if (isPlugin)
  1796. saveExternalConnections = false;
  1797. else if (std::strcmp(getCurrentDriverName(), "JACK") != 0)
  1798. saveExternalConnections = true;
  1799. else if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr)
  1800. saveExternalConnections = false;
  1801. else if (std::getenv("LADISH_APP_NAME") != nullptr)
  1802. saveExternalConnections = false;
  1803. else if (std::getenv("NSM_URL") != nullptr)
  1804. saveExternalConnections = false;
  1805. else
  1806. saveExternalConnections = true;
  1807. if (saveExternalConnections)
  1808. {
  1809. if (const char* const* const patchbayConns = getPatchbayConnections(true))
  1810. {
  1811. MemoryOutputStream outPatchbay(2048);
  1812. outPatchbay << "\n <ExternalPatchbay>\n";
  1813. for (int i=0; patchbayConns[i] != nullptr && patchbayConns[i+1] != nullptr; ++i, ++i )
  1814. {
  1815. const char* const connSource(patchbayConns[i]);
  1816. const char* const connTarget(patchbayConns[i+1]);
  1817. CARLA_SAFE_ASSERT_CONTINUE(connSource != nullptr && connSource[0] != '\0');
  1818. CARLA_SAFE_ASSERT_CONTINUE(connTarget != nullptr && connTarget[0] != '\0');
  1819. outPatchbay << " <Connection>\n";
  1820. outPatchbay << " <Source>" << xmlSafeString(connSource, true) << "</Source>\n";
  1821. outPatchbay << " <Target>" << xmlSafeString(connTarget, true) << "</Target>\n";
  1822. outPatchbay << " </Connection>\n";
  1823. }
  1824. outPatchbay << " </ExternalPatchbay>\n";
  1825. outStream << outPatchbay;
  1826. }
  1827. }
  1828. #endif
  1829. outStream << "</CARLA-PROJECT>\n";
  1830. }
  1831. static String findBinaryInCustomPath(const char* const searchPath, const char* const binary)
  1832. {
  1833. const StringArray searchPaths(StringArray::fromTokens(searchPath, CARLA_OS_SPLIT_STR, ""));
  1834. // try direct filename first
  1835. String jbinary(binary);
  1836. // adjust for current platform
  1837. #ifdef CARLA_OS_WIN
  1838. if (jbinary[0] == '/')
  1839. jbinary = "C:" + jbinary.replaceCharacter('/', '\\');
  1840. #else
  1841. if (jbinary[1] == ':' && (jbinary[2] == '\\' || jbinary[2] == '/'))
  1842. jbinary = jbinary.substring(2).replaceCharacter('\\', '/');
  1843. #endif
  1844. String filename = File(jbinary).getFileName();
  1845. int searchFlags = File::findFiles|File::ignoreHiddenFiles;
  1846. #ifdef CARLA_OS_MAC
  1847. if (filename.endsWithIgnoreCase(".vst") || filename.endsWithIgnoreCase(".vst3"))
  1848. searchFlags |= File::findDirectories;
  1849. #endif
  1850. Array<File> results;
  1851. for (const String *it=searchPaths.begin(), *end=searchPaths.end(); it != end; ++it)
  1852. {
  1853. const File path(*it);
  1854. results.clear();
  1855. path.findChildFiles(results, searchFlags, true, filename);
  1856. if (results.size() > 0)
  1857. return results.getFirst().getFullPathName();
  1858. }
  1859. // try changing extension
  1860. #if defined(CARLA_OS_MAC)
  1861. if (filename.endsWithIgnoreCase(".dll") || filename.endsWithIgnoreCase(".so"))
  1862. filename = File(jbinary).getFileNameWithoutExtension() + ".dylib";
  1863. #elif defined(CARLA_OS_WIN)
  1864. if (filename.endsWithIgnoreCase(".dylib") || filename.endsWithIgnoreCase(".so"))
  1865. filename = File(jbinary).getFileNameWithoutExtension() + ".dll";
  1866. #else
  1867. if (filename.endsWithIgnoreCase(".dll") || filename.endsWithIgnoreCase(".dylib"))
  1868. filename = File(jbinary).getFileNameWithoutExtension() + ".so";
  1869. #endif
  1870. else
  1871. return String();
  1872. for (const String *it=searchPaths.begin(), *end=searchPaths.end(); it != end; ++it)
  1873. {
  1874. const File path(*it);
  1875. results.clear();
  1876. path.findChildFiles(results, searchFlags, true, filename);
  1877. if (results.size() > 0)
  1878. return results.getFirst().getFullPathName();
  1879. }
  1880. return String();
  1881. }
  1882. bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc)
  1883. {
  1884. CarlaScopedPointer<XmlElement> xmlElement(xmlDoc.getDocumentElement(true));
  1885. CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to parse project file");
  1886. const String& xmlType(xmlElement->getTagName());
  1887. const bool isPreset(xmlType.equalsIgnoreCase("carla-preset"));
  1888. if (! (xmlType.equalsIgnoreCase("carla-project") || isPreset))
  1889. {
  1890. callback(true, true, ENGINE_CALLBACK_PROJECT_LOAD_FINISHED, 0, 0, 0, 0, 0.0f, nullptr);
  1891. setLastError("Not a valid Carla project or preset file");
  1892. return false;
  1893. }
  1894. pData->actionCanceled = false;
  1895. callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, 0, 1, 0, 0, 0.0f, "Loading project");
  1896. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1897. const CarlaScopedValueSetter<bool> csvs(pData->loadingProject, true, false);
  1898. #endif
  1899. // completely load file
  1900. xmlElement = xmlDoc.getDocumentElement(false);
  1901. CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to completely parse project file");
  1902. callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  1903. if (pData->aboutToClose)
  1904. return true;
  1905. if (pData->actionCanceled)
  1906. {
  1907. setLastError("Project load canceled");
  1908. return false;
  1909. }
  1910. const bool isPlugin(getType() == kEngineTypePlugin);
  1911. // load engine settings first of all
  1912. if (XmlElement* const elem = isPreset ? nullptr : xmlElement->getChildByName("EngineSettings"))
  1913. {
  1914. for (XmlElement* settElem = elem->getFirstChildElement(); settElem != nullptr; settElem = settElem->getNextElement())
  1915. {
  1916. const String& tag(settElem->getTagName());
  1917. const String text(settElem->getAllSubText().trim());
  1918. /** some settings might be incorrect or require extra work,
  1919. so we call setOption rather than modifying them direly */
  1920. int option = -1;
  1921. int value = 0;
  1922. const char* valueStr = nullptr;
  1923. /**/ if (tag == "ForceStereo")
  1924. {
  1925. option = ENGINE_OPTION_FORCE_STEREO;
  1926. value = text == "true" ? 1 : 0;
  1927. }
  1928. else if (tag == "PreferPluginBridges")
  1929. {
  1930. option = ENGINE_OPTION_PREFER_PLUGIN_BRIDGES;
  1931. value = text == "true" ? 1 : 0;
  1932. }
  1933. else if (tag == "PreferUiBridges")
  1934. {
  1935. option = ENGINE_OPTION_PREFER_UI_BRIDGES;
  1936. value = text == "true" ? 1 : 0;
  1937. }
  1938. else if (tag == "UIsAlwaysOnTop")
  1939. {
  1940. option = ENGINE_OPTION_UIS_ALWAYS_ON_TOP;
  1941. value = text == "true" ? 1 : 0;
  1942. }
  1943. else if (tag == "MaxParameters")
  1944. {
  1945. option = ENGINE_OPTION_MAX_PARAMETERS;
  1946. value = text.getIntValue();
  1947. }
  1948. else if (tag == "UIBridgesTimeout")
  1949. {
  1950. option = ENGINE_OPTION_UI_BRIDGES_TIMEOUT;
  1951. value = text.getIntValue();
  1952. }
  1953. else if (isPlugin)
  1954. {
  1955. /**/ if (tag == "LADSPA_PATH")
  1956. {
  1957. option = ENGINE_OPTION_PLUGIN_PATH;
  1958. value = PLUGIN_LADSPA;
  1959. valueStr = text.toRawUTF8();
  1960. }
  1961. else if (tag == "DSSI_PATH")
  1962. {
  1963. option = ENGINE_OPTION_PLUGIN_PATH;
  1964. value = PLUGIN_DSSI;
  1965. valueStr = text.toRawUTF8();
  1966. }
  1967. else if (tag == "LV2_PATH")
  1968. {
  1969. option = ENGINE_OPTION_PLUGIN_PATH;
  1970. value = PLUGIN_LV2;
  1971. valueStr = text.toRawUTF8();
  1972. }
  1973. else if (tag == "VST2_PATH")
  1974. {
  1975. option = ENGINE_OPTION_PLUGIN_PATH;
  1976. value = PLUGIN_VST2;
  1977. valueStr = text.toRawUTF8();
  1978. }
  1979. else if (tag.equalsIgnoreCase("VST3_PATH"))
  1980. {
  1981. option = ENGINE_OPTION_PLUGIN_PATH;
  1982. value = PLUGIN_VST3;
  1983. valueStr = text.toRawUTF8();
  1984. }
  1985. else if (tag == "SF2_PATH")
  1986. {
  1987. option = ENGINE_OPTION_PLUGIN_PATH;
  1988. value = PLUGIN_SF2;
  1989. valueStr = text.toRawUTF8();
  1990. }
  1991. else if (tag == "SFZ_PATH")
  1992. {
  1993. option = ENGINE_OPTION_PLUGIN_PATH;
  1994. value = PLUGIN_SFZ;
  1995. valueStr = text.toRawUTF8();
  1996. }
  1997. }
  1998. if (option == -1)
  1999. {
  2000. // check old stuff, unhandled now
  2001. if (tag == "GIG_PATH")
  2002. continue;
  2003. // ignored tags
  2004. if (tag == "LADSPA_PATH" || tag == "DSSI_PATH" || tag == "LV2_PATH" || tag == "VST2_PATH")
  2005. continue;
  2006. if (tag == "VST3_PATH" || tag == "AU_PATH")
  2007. continue;
  2008. if (tag == "SF2_PATH" || tag == "SFZ_PATH")
  2009. continue;
  2010. // hmm something is wrong..
  2011. carla_stderr2("CarlaEngine::loadProjectInternal() - Unhandled option '%s'", tag.toRawUTF8());
  2012. continue;
  2013. }
  2014. setOption(static_cast<EngineOption>(option), value, valueStr);
  2015. }
  2016. callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2017. if (pData->aboutToClose)
  2018. return true;
  2019. if (pData->actionCanceled)
  2020. {
  2021. setLastError("Project load canceled");
  2022. return false;
  2023. }
  2024. }
  2025. // now setup transport
  2026. if (XmlElement* const elem = (isPreset || isPlugin) ? nullptr : xmlElement->getChildByName("Transport"))
  2027. {
  2028. if (XmlElement* const bpmElem = elem->getChildByName("BeatsPerMinute"))
  2029. {
  2030. const String bpmText(bpmElem->getAllSubText().trim());
  2031. const double bpm = bpmText.getDoubleValue();
  2032. // some sane limits
  2033. if (bpm >= 20.0 && bpm < 400.0)
  2034. pData->time.setBPM(bpm);
  2035. callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2036. if (pData->aboutToClose)
  2037. return true;
  2038. if (pData->actionCanceled)
  2039. {
  2040. setLastError("Project load canceled");
  2041. return false;
  2042. }
  2043. }
  2044. }
  2045. // and we handle plugins
  2046. for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
  2047. {
  2048. const String& tagName(elem->getTagName());
  2049. if (isPreset || tagName == "Plugin")
  2050. {
  2051. CarlaStateSave stateSave;
  2052. stateSave.fillFromXmlElement(isPreset ? xmlElement.get() : elem);
  2053. callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2054. if (pData->aboutToClose)
  2055. return true;
  2056. if (pData->actionCanceled)
  2057. {
  2058. setLastError("Project load canceled");
  2059. return false;
  2060. }
  2061. CARLA_SAFE_ASSERT_CONTINUE(stateSave.type != nullptr);
  2062. #ifndef BUILD_BRIDGE
  2063. // compatibility code to load projects with GIG files
  2064. // FIXME Remove on 2.1 release
  2065. if (std::strcmp(stateSave.type, "GIG") == 0)
  2066. {
  2067. if (addPlugin(PLUGIN_LV2, "", stateSave.name, "http://linuxsampler.org/plugins/linuxsampler", 0, nullptr))
  2068. {
  2069. const uint pluginId = pData->curPluginCount;
  2070. if (CarlaPlugin* const plugin = pData->plugins[pluginId].plugin)
  2071. {
  2072. callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2073. if (pData->aboutToClose)
  2074. return true;
  2075. if (pData->actionCanceled)
  2076. {
  2077. setLastError("Project load canceled");
  2078. return false;
  2079. }
  2080. String lsState;
  2081. lsState << "0.35\n";
  2082. lsState << "18 0 Chromatic\n";
  2083. lsState << "18 1 Drum Kits\n";
  2084. lsState << "20 0\n";
  2085. lsState << "0 1 " << stateSave.binary << "\n";
  2086. lsState << "0 0 0 0 1 0 GIG\n";
  2087. plugin->setCustomData(LV2_ATOM__String, "http://linuxsampler.org/schema#state-string", lsState.toRawUTF8(), true);
  2088. plugin->restoreLV2State();
  2089. plugin->setDryWet(stateSave.dryWet, true, true);
  2090. plugin->setVolume(stateSave.volume, true, true);
  2091. plugin->setBalanceLeft(stateSave.balanceLeft, true, true);
  2092. plugin->setBalanceRight(stateSave.balanceRight, true, true);
  2093. plugin->setPanning(stateSave.panning, true, true);
  2094. plugin->setCtrlChannel(stateSave.ctrlChannel, true, true);
  2095. plugin->setActive(stateSave.active, true, true);
  2096. plugin->setEnabled(true);
  2097. ++pData->curPluginCount;
  2098. callback(true, true, ENGINE_CALLBACK_PLUGIN_ADDED, pluginId, 0, 0, 0, 0.0f, plugin->getName());
  2099. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  2100. pData->graph.addPlugin(plugin);
  2101. }
  2102. else
  2103. {
  2104. carla_stderr2("Failed to get new plugin, state will not be restored correctly\n");
  2105. }
  2106. }
  2107. else
  2108. {
  2109. carla_stderr2("Failed to load a linuxsampler LV2 plugin, GIG file won't be loaded");
  2110. }
  2111. continue;
  2112. }
  2113. #endif
  2114. const void* extraStuff = nullptr;
  2115. static const char kTrue[] = "true";
  2116. const PluginType ptype(getPluginTypeFromString(stateSave.type));
  2117. switch (ptype)
  2118. {
  2119. case PLUGIN_SF2:
  2120. if (CarlaString(stateSave.label).endsWith(" (16 outs)"))
  2121. extraStuff = kTrue;
  2122. // fall through
  2123. case PLUGIN_LADSPA:
  2124. case PLUGIN_DSSI:
  2125. case PLUGIN_VST2:
  2126. case PLUGIN_VST3:
  2127. case PLUGIN_SFZ:
  2128. if (stateSave.binary != nullptr && stateSave.binary[0] != '\0' &&
  2129. ! (File::isAbsolutePath(stateSave.binary) && File(stateSave.binary).exists()))
  2130. {
  2131. const char* searchPath;
  2132. switch (ptype)
  2133. {
  2134. case PLUGIN_LADSPA: searchPath = pData->options.pathLADSPA; break;
  2135. case PLUGIN_DSSI: searchPath = pData->options.pathDSSI; break;
  2136. case PLUGIN_VST2: searchPath = pData->options.pathVST2; break;
  2137. case PLUGIN_VST3: searchPath = pData->options.pathVST3; break;
  2138. case PLUGIN_SF2: searchPath = pData->options.pathSF2; break;
  2139. case PLUGIN_SFZ: searchPath = pData->options.pathSFZ; break;
  2140. default: searchPath = nullptr; break;
  2141. }
  2142. if (searchPath != nullptr && searchPath[0] != '\0')
  2143. {
  2144. carla_stderr("Plugin binary '%s' doesn't exist on this filesystem, let's look for it...",
  2145. stateSave.binary);
  2146. String result = findBinaryInCustomPath(searchPath, stateSave.binary);
  2147. if (result.isEmpty())
  2148. {
  2149. switch (ptype)
  2150. {
  2151. case PLUGIN_LADSPA: searchPath = std::getenv("LADSPA_PATH"); break;
  2152. case PLUGIN_DSSI: searchPath = std::getenv("DSSI_PATH"); break;
  2153. case PLUGIN_VST2: searchPath = std::getenv("VST_PATH"); break;
  2154. case PLUGIN_VST3: searchPath = std::getenv("VST3_PATH"); break;
  2155. case PLUGIN_SF2: searchPath = std::getenv("SF2_PATH"); break;
  2156. case PLUGIN_SFZ: searchPath = std::getenv("SFZ_PATH"); break;
  2157. default: searchPath = nullptr; break;
  2158. }
  2159. if (searchPath != nullptr && searchPath[0] != '\0')
  2160. result = findBinaryInCustomPath(searchPath, stateSave.binary);
  2161. }
  2162. if (result.isNotEmpty())
  2163. {
  2164. delete[] stateSave.binary;
  2165. stateSave.binary = carla_strdup(result.toRawUTF8());
  2166. carla_stderr("Found it! :)");
  2167. }
  2168. else
  2169. {
  2170. carla_stderr("Damn, we failed... :(");
  2171. }
  2172. }
  2173. }
  2174. break;
  2175. default:
  2176. break;
  2177. }
  2178. BinaryType btype;
  2179. switch (ptype)
  2180. {
  2181. case PLUGIN_LADSPA:
  2182. case PLUGIN_DSSI:
  2183. case PLUGIN_LV2:
  2184. case PLUGIN_VST2:
  2185. btype = getBinaryTypeFromFile(stateSave.binary);
  2186. break;
  2187. default:
  2188. btype = BINARY_NATIVE;
  2189. break;
  2190. }
  2191. if (addPlugin(btype, ptype, stateSave.binary,
  2192. stateSave.name, stateSave.label, stateSave.uniqueId, extraStuff, stateSave.options))
  2193. {
  2194. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2195. const uint pluginId = pData->curPluginCount;
  2196. #else
  2197. const uint pluginId = 0;
  2198. #endif
  2199. if (CarlaPlugin* const plugin = pData->plugins[pluginId].plugin)
  2200. {
  2201. callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2202. if (pData->aboutToClose)
  2203. return true;
  2204. if (pData->actionCanceled)
  2205. {
  2206. setLastError("Project load canceled");
  2207. return false;
  2208. }
  2209. // deactivate bridge client-side ping check, since some plugins block during load
  2210. if ((plugin->getHints() & PLUGIN_IS_BRIDGE) != 0 && ! isPreset)
  2211. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "false", false);
  2212. plugin->loadStateSave(stateSave);
  2213. /* NOTE: The following code is the same as the end of addPlugin().
  2214. * When project is loading we do not enable the plugin right away,
  2215. * as we want to load state first.
  2216. */
  2217. plugin->setEnabled(true);
  2218. ++pData->curPluginCount;
  2219. callback(true, true, ENGINE_CALLBACK_PLUGIN_ADDED, pluginId, 0, 0, 0, 0.0f, plugin->getName());
  2220. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2221. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  2222. pData->graph.addPlugin(plugin);
  2223. #endif
  2224. }
  2225. else
  2226. {
  2227. carla_stderr2("Failed to get new plugin, state will not be restored correctly\n");
  2228. }
  2229. }
  2230. else
  2231. {
  2232. carla_stderr2("Failed to load a plugin '%s', error was:\n%s", stateSave.name, getLastError());
  2233. }
  2234. }
  2235. if (isPreset)
  2236. {
  2237. callback(true, true, ENGINE_CALLBACK_PROJECT_LOAD_FINISHED, 0, 0, 0, 0, 0.0f, nullptr);
  2238. callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, 0, 0, 0, 0, 0.0f, "Loading project");
  2239. return true;
  2240. }
  2241. }
  2242. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2243. // tell bridges we're done loading
  2244. for (uint i=0; i < pData->curPluginCount; ++i)
  2245. {
  2246. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  2247. if (plugin != nullptr && plugin->isEnabled() && (plugin->getHints() & PLUGIN_IS_BRIDGE) != 0)
  2248. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "true", false);
  2249. }
  2250. callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2251. if (pData->aboutToClose)
  2252. return true;
  2253. if (pData->actionCanceled)
  2254. {
  2255. setLastError("Project load canceled");
  2256. return false;
  2257. }
  2258. bool hasInternalConnections = false;
  2259. // and now we handle connections (internal)
  2260. if (XmlElement* const elem = xmlElement->getChildByName("Patchbay"))
  2261. {
  2262. hasInternalConnections = true;
  2263. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  2264. {
  2265. CarlaString sourcePort, targetPort;
  2266. for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement())
  2267. {
  2268. const String& patchTag(patchElem->getTagName());
  2269. if (patchTag != "Connection")
  2270. continue;
  2271. sourcePort.clear();
  2272. targetPort.clear();
  2273. for (XmlElement* connElem = patchElem->getFirstChildElement(); connElem != nullptr; connElem = connElem->getNextElement())
  2274. {
  2275. const String& tag(connElem->getTagName());
  2276. const String text(connElem->getAllSubText().trim());
  2277. /**/ if (tag == "Source")
  2278. sourcePort = xmlSafeString(text, false).toRawUTF8();
  2279. else if (tag == "Target")
  2280. targetPort = xmlSafeString(text, false).toRawUTF8();
  2281. }
  2282. if (sourcePort.isNotEmpty() && targetPort.isNotEmpty())
  2283. restorePatchbayConnection(false, sourcePort, targetPort);
  2284. }
  2285. callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2286. if (pData->aboutToClose)
  2287. return true;
  2288. if (pData->actionCanceled)
  2289. {
  2290. setLastError("Project load canceled");
  2291. return false;
  2292. }
  2293. }
  2294. }
  2295. // if we're running inside some session-manager (and using JACK), let them handle the external connections
  2296. bool loadExternalConnections;
  2297. /**/ if (std::strcmp(getCurrentDriverName(), "JACK") != 0)
  2298. loadExternalConnections = true;
  2299. else if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr)
  2300. loadExternalConnections = false;
  2301. else if (std::getenv("LADISH_APP_NAME") != nullptr)
  2302. loadExternalConnections = false;
  2303. else if (std::getenv("NSM_URL") != nullptr)
  2304. loadExternalConnections = false;
  2305. else
  2306. loadExternalConnections = true;
  2307. // plus external connections too
  2308. if (loadExternalConnections)
  2309. {
  2310. const bool loadingAsExternal = pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY &&
  2311. hasInternalConnections;
  2312. for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
  2313. {
  2314. const String& tagName(elem->getTagName());
  2315. // check if we want to load patchbay-mode connections into an external (multi-client) graph
  2316. if (tagName == "Patchbay")
  2317. {
  2318. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  2319. continue;
  2320. }
  2321. // or load external patchbay connections
  2322. else if (tagName != "ExternalPatchbay")
  2323. {
  2324. continue;
  2325. }
  2326. CarlaString sourcePort, targetPort;
  2327. for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement())
  2328. {
  2329. const String& patchTag(patchElem->getTagName());
  2330. if (patchTag != "Connection")
  2331. continue;
  2332. sourcePort.clear();
  2333. targetPort.clear();
  2334. for (XmlElement* connElem = patchElem->getFirstChildElement(); connElem != nullptr; connElem = connElem->getNextElement())
  2335. {
  2336. const String& tag(connElem->getTagName());
  2337. const String text(connElem->getAllSubText().trim());
  2338. /**/ if (tag == "Source")
  2339. sourcePort = xmlSafeString(text, false).toRawUTF8();
  2340. else if (tag == "Target")
  2341. targetPort = xmlSafeString(text, false).toRawUTF8();
  2342. }
  2343. if (sourcePort.isNotEmpty() && targetPort.isNotEmpty())
  2344. restorePatchbayConnection(loadingAsExternal, sourcePort, targetPort);
  2345. }
  2346. break;
  2347. }
  2348. }
  2349. #endif
  2350. callback(true, true, ENGINE_CALLBACK_PROJECT_LOAD_FINISHED, 0, 0, 0, 0, 0.0f, nullptr);
  2351. callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, 0, 0, 0, 0, 0.0f, "Loading project");
  2352. return true;
  2353. }
  2354. // -----------------------------------------------------------------------
  2355. CARLA_BACKEND_END_NAMESPACE