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

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
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
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
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
7 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 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
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
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
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
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
10 years ago
10 years ago
9 years ago
10 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
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645
  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2023 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 "CarlaEngineClient.hpp"
  24. #include "CarlaEngineInit.hpp"
  25. #include "CarlaEngineInternal.hpp"
  26. #include "CarlaPlugin.hpp"
  27. #include "CarlaBackendUtils.hpp"
  28. #include "CarlaBinaryUtils.hpp"
  29. #include "CarlaEngineUtils.hpp"
  30. #include "CarlaMathUtils.hpp"
  31. #include "CarlaPipeUtils.hpp"
  32. #include "CarlaProcessUtils.hpp"
  33. #include "CarlaScopeUtils.hpp"
  34. #include "CarlaStateUtils.hpp"
  35. #include "CarlaMIDI.h"
  36. #include "jackbridge/JackBridge.hpp"
  37. #include "water/files/File.h"
  38. #include "water/streams/MemoryOutputStream.h"
  39. #include "water/xml/XmlDocument.h"
  40. #include "water/xml/XmlElement.h"
  41. #ifdef CARLA_OS_MAC
  42. # include "CarlaMacUtils.hpp"
  43. # if defined(CARLA_OS_64BIT) && defined(HAVE_LIBMAGIC) && ! defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
  44. # define ADAPT_FOR_APPLE_SILLICON
  45. # endif
  46. #endif
  47. #include <map>
  48. // FIXME Remove on 2.1 release
  49. #include "lv2/atom.h"
  50. using water::Array;
  51. using water::CharPointer_UTF8;
  52. using water::File;
  53. using water::MemoryOutputStream;
  54. using water::String;
  55. using water::StringArray;
  56. using water::XmlDocument;
  57. using water::XmlElement;
  58. // #define SFZ_FILES_USING_SFIZZ
  59. CARLA_BACKEND_START_NAMESPACE
  60. // -----------------------------------------------------------------------
  61. // Carla Engine
  62. CarlaEngine::CarlaEngine()
  63. : pData(new ProtectedData(this))
  64. {
  65. carla_debug("CarlaEngine::CarlaEngine()");
  66. }
  67. CarlaEngine::~CarlaEngine()
  68. {
  69. carla_debug("CarlaEngine::~CarlaEngine()");
  70. delete pData;
  71. }
  72. // -----------------------------------------------------------------------
  73. // Static calls
  74. uint CarlaEngine::getDriverCount()
  75. {
  76. carla_debug("CarlaEngine::getDriverCount()");
  77. using namespace EngineInit;
  78. uint count = 0;
  79. #ifdef HAVE_JACK
  80. if (jackbridge_is_ok())
  81. ++count;
  82. #endif
  83. #ifdef USING_JUCE_AUDIO_DEVICES
  84. count += getJuceApiCount();
  85. #endif
  86. #ifdef USING_RTAUDIO
  87. count += getRtAudioApiCount();
  88. #endif
  89. #ifdef HAVE_SDL
  90. ++count;
  91. #endif
  92. return count;
  93. }
  94. const char* CarlaEngine::getDriverName(const uint index)
  95. {
  96. carla_debug("CarlaEngine::getDriverName(%u)", index);
  97. using namespace EngineInit;
  98. uint index2 = index;
  99. #ifdef HAVE_JACK
  100. if (jackbridge_is_ok())
  101. {
  102. if (index2 == 0)
  103. return "JACK";
  104. --index2;
  105. }
  106. #endif
  107. #ifdef USING_JUCE_AUDIO_DEVICES
  108. if (const uint count = getJuceApiCount())
  109. {
  110. if (index2 < count)
  111. return getJuceApiName(index2);
  112. index2 -= count;
  113. }
  114. #endif
  115. #ifdef USING_RTAUDIO
  116. if (const uint count = getRtAudioApiCount())
  117. {
  118. if (index2 < count)
  119. return getRtAudioApiName(index2);
  120. index2 -= count;
  121. }
  122. #endif
  123. #ifdef HAVE_SDL
  124. if (index2 == 0)
  125. return "SDL";
  126. --index2;
  127. #endif
  128. carla_stderr("CarlaEngine::getDriverName(%u) - invalid index %u", index, index2);
  129. return nullptr;
  130. }
  131. const char* const* CarlaEngine::getDriverDeviceNames(const uint index)
  132. {
  133. carla_debug("CarlaEngine::getDriverDeviceNames(%u)", index);
  134. using namespace EngineInit;
  135. uint index2 = index;
  136. #ifdef HAVE_JACK
  137. if (jackbridge_is_ok())
  138. {
  139. if (index2 == 0)
  140. {
  141. static const char* ret[3] = { "Auto-Connect ON", "Auto-Connect OFF", nullptr };
  142. return ret;
  143. }
  144. --index2;
  145. }
  146. #endif
  147. #ifdef USING_JUCE_AUDIO_DEVICES
  148. if (const uint count = getJuceApiCount())
  149. {
  150. if (index2 < count)
  151. return getJuceApiDeviceNames(index2);
  152. index2 -= count;
  153. }
  154. #endif
  155. #ifdef USING_RTAUDIO
  156. if (const uint count = getRtAudioApiCount())
  157. {
  158. if (index2 < count)
  159. return getRtAudioApiDeviceNames(index2);
  160. index2 -= count;
  161. }
  162. #endif
  163. #ifdef HAVE_SDL
  164. if (index2 == 0)
  165. return getSDLDeviceNames();
  166. --index2;
  167. #endif
  168. carla_stderr("CarlaEngine::getDriverDeviceNames(%u) - invalid index %u", index, index2);
  169. return nullptr;
  170. }
  171. const EngineDriverDeviceInfo* CarlaEngine::getDriverDeviceInfo(const uint index, const char* const deviceName)
  172. {
  173. carla_debug("CarlaEngine::getDriverDeviceInfo(%u, \"%s\")", index, deviceName);
  174. using namespace EngineInit;
  175. uint index2 = index;
  176. #ifdef HAVE_JACK
  177. if (jackbridge_is_ok())
  178. {
  179. if (index2 == 0)
  180. {
  181. static EngineDriverDeviceInfo devInfo;
  182. devInfo.hints = ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE;
  183. devInfo.bufferSizes = nullptr;
  184. devInfo.sampleRates = nullptr;
  185. return &devInfo;
  186. }
  187. }
  188. --index2;
  189. #endif
  190. #ifdef USING_JUCE_AUDIO_DEVICES
  191. if (const uint count = getJuceApiCount())
  192. {
  193. if (index2 < count)
  194. return getJuceDeviceInfo(index2, deviceName);
  195. index2 -= count;
  196. }
  197. #endif
  198. #ifdef USING_RTAUDIO
  199. if (const uint count = getRtAudioApiCount())
  200. {
  201. if (index2 < count)
  202. return getRtAudioDeviceInfo(index2, deviceName);
  203. index2 -= count;
  204. }
  205. #endif
  206. #ifdef HAVE_SDL
  207. if (index2 == 0)
  208. {
  209. static uint32_t sdlBufferSizes[] = { 512, 1024, 2048, 4096, 8192, 0 };
  210. static double sdlSampleRates[] = { 44100.0, 48000.0, 88200.0, 96000.0, 0.0 };
  211. static EngineDriverDeviceInfo devInfo;
  212. devInfo.hints = 0x0;
  213. devInfo.bufferSizes = sdlBufferSizes;
  214. devInfo.sampleRates = sdlSampleRates;
  215. return &devInfo;
  216. }
  217. --index2;
  218. #endif
  219. carla_stderr("CarlaEngine::getDriverDeviceInfo(%u, \"%s\") - invalid index %u", index, index2, deviceName);
  220. return nullptr;
  221. }
  222. bool CarlaEngine::showDriverDeviceControlPanel(const uint index, const char* const deviceName)
  223. {
  224. carla_debug("CarlaEngine::showDriverDeviceControlPanel(%u, \"%s\")", index, deviceName);
  225. using namespace EngineInit;
  226. uint index2 = index;
  227. #ifdef HAVE_JACK
  228. if (jackbridge_is_ok())
  229. {
  230. if (index2 == 0)
  231. return false;
  232. --index2;
  233. }
  234. #endif
  235. #ifdef USING_JUCE_AUDIO_DEVICES
  236. if (const uint count = getJuceApiCount())
  237. {
  238. if (index2 < count)
  239. return showJuceDeviceControlPanel(index2, deviceName);
  240. index2 -= count;
  241. }
  242. #endif
  243. #ifdef USING_RTAUDIO
  244. if (const uint count = getRtAudioApiCount())
  245. {
  246. if (index2 < count)
  247. return false;
  248. index2 -= count;
  249. }
  250. #endif
  251. #ifdef HAVE_SDL
  252. if (index2 == 0)
  253. return false;
  254. --index2;
  255. #endif
  256. carla_stderr("CarlaEngine::showDriverDeviceControlPanel(%u, \"%s\") - invalid index %u", index, index2, deviceName);
  257. return false;
  258. }
  259. CarlaEngine* CarlaEngine::newDriverByName(const char* const driverName)
  260. {
  261. CARLA_SAFE_ASSERT_RETURN(driverName != nullptr && driverName[0] != '\0', nullptr);
  262. carla_debug("CarlaEngine::newDriverByName(\"%s\")", driverName);
  263. using namespace EngineInit;
  264. #ifdef HAVE_JACK
  265. if (std::strcmp(driverName, "JACK") == 0)
  266. return newJack();
  267. #endif
  268. #if !(defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) || defined(CARLA_OS_WASM) || defined(STATIC_PLUGIN_TARGET))
  269. if (std::strcmp(driverName, "Dummy") == 0)
  270. return newDummy();
  271. #endif
  272. #ifdef USING_JUCE_AUDIO_DEVICES
  273. // -------------------------------------------------------------------
  274. // linux
  275. if (std::strcmp(driverName, "ALSA") == 0)
  276. return newJuce(AUDIO_API_ALSA);
  277. // -------------------------------------------------------------------
  278. // macos
  279. if (std::strcmp(driverName, "CoreAudio") == 0)
  280. return newJuce(AUDIO_API_COREAUDIO);
  281. // -------------------------------------------------------------------
  282. // windows
  283. if (std::strcmp(driverName, "ASIO") == 0)
  284. return newJuce(AUDIO_API_ASIO);
  285. if (std::strcmp(driverName, "DirectSound") == 0)
  286. return newJuce(AUDIO_API_DIRECTSOUND);
  287. if (std::strcmp(driverName, "WASAPI") == 0 || std::strcmp(driverName, "Windows Audio") == 0)
  288. return newJuce(AUDIO_API_WASAPI);
  289. #endif
  290. #ifdef USING_RTAUDIO
  291. // -------------------------------------------------------------------
  292. // common
  293. if (std::strncmp(driverName, "JACK ", 5) == 0)
  294. return newRtAudio(AUDIO_API_JACK);
  295. if (std::strcmp(driverName, "OSS") == 0)
  296. return newRtAudio(AUDIO_API_OSS);
  297. // -------------------------------------------------------------------
  298. // linux
  299. if (std::strcmp(driverName, "ALSA") == 0)
  300. return newRtAudio(AUDIO_API_ALSA);
  301. if (std::strcmp(driverName, "PulseAudio") == 0)
  302. return newRtAudio(AUDIO_API_PULSEAUDIO);
  303. // -------------------------------------------------------------------
  304. // macos
  305. if (std::strcmp(driverName, "CoreAudio") == 0)
  306. return newRtAudio(AUDIO_API_COREAUDIO);
  307. // -------------------------------------------------------------------
  308. // windows
  309. if (std::strcmp(driverName, "ASIO") == 0)
  310. return newRtAudio(AUDIO_API_ASIO);
  311. if (std::strcmp(driverName, "DirectSound") == 0)
  312. return newRtAudio(AUDIO_API_DIRECTSOUND);
  313. if (std::strcmp(driverName, "WASAPI") == 0)
  314. return newRtAudio(AUDIO_API_WASAPI);
  315. #endif
  316. #ifdef HAVE_SDL
  317. if (std::strcmp(driverName, "SDL") == 0)
  318. return newSDL();
  319. #endif
  320. carla_stderr("CarlaEngine::newDriverByName(\"%s\") - invalid driver name", driverName);
  321. return nullptr;
  322. }
  323. // -----------------------------------------------------------------------
  324. // Constant values
  325. uint CarlaEngine::getMaxClientNameSize() const noexcept
  326. {
  327. return STR_MAX/2;
  328. }
  329. uint CarlaEngine::getMaxPortNameSize() const noexcept
  330. {
  331. return STR_MAX;
  332. }
  333. uint CarlaEngine::getCurrentPluginCount() const noexcept
  334. {
  335. return pData->curPluginCount;
  336. }
  337. uint CarlaEngine::getMaxPluginNumber() const noexcept
  338. {
  339. return pData->maxPluginNumber;
  340. }
  341. // -----------------------------------------------------------------------
  342. // Virtual, per-engine type calls
  343. bool CarlaEngine::close()
  344. {
  345. carla_debug("CarlaEngine::close()");
  346. if (pData->curPluginCount != 0)
  347. {
  348. pData->aboutToClose = true;
  349. removeAllPlugins();
  350. }
  351. pData->close();
  352. callback(true, true, ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0, 0.0f, nullptr);
  353. return true;
  354. }
  355. bool CarlaEngine::usesConstantBufferSize() const noexcept
  356. {
  357. return true;
  358. }
  359. void CarlaEngine::idle() noexcept
  360. {
  361. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,);
  362. CARLA_SAFE_ASSERT_RETURN(pData->nextPluginId == pData->maxPluginNumber,);
  363. CARLA_SAFE_ASSERT_RETURN(getType() != kEngineTypePlugin,);
  364. const bool engineNotRunning = !isRunning();
  365. const bool engineHasIdleOnMainThread = hasIdleOnMainThread();
  366. for (uint i=0; i < pData->curPluginCount; ++i)
  367. {
  368. if (const CarlaPluginPtr plugin = pData->plugins[i].plugin)
  369. {
  370. if (plugin->isEnabled())
  371. {
  372. const uint hints = plugin->getHints();
  373. if (engineNotRunning)
  374. {
  375. try {
  376. plugin->idle();
  377. } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin idle");
  378. if (hints & PLUGIN_HAS_CUSTOM_UI)
  379. {
  380. try {
  381. plugin->uiIdle();
  382. } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin uiIdle");
  383. }
  384. }
  385. else
  386. {
  387. if (engineHasIdleOnMainThread && (hints & PLUGIN_NEEDS_MAIN_THREAD_IDLE) != 0)
  388. {
  389. try {
  390. plugin->idle();
  391. } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin idle");
  392. }
  393. if ((hints & PLUGIN_HAS_CUSTOM_UI) != 0 && (hints & PLUGIN_NEEDS_UI_MAIN_THREAD) != 0)
  394. {
  395. try {
  396. plugin->uiIdle();
  397. } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin uiIdle");
  398. }
  399. }
  400. }
  401. }
  402. }
  403. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
  404. pData->osc.idle();
  405. #endif
  406. pData->deletePluginsAsNeeded();
  407. }
  408. CarlaEngineClient* CarlaEngine::addClient(CarlaPluginPtr plugin)
  409. {
  410. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  411. return new CarlaEngineClientForStandalone(*this, pData->graph, plugin);
  412. #else
  413. return new CarlaEngineClientForBridge(*this);
  414. // unused
  415. (void)plugin;
  416. #endif
  417. }
  418. float CarlaEngine::getDSPLoad() const noexcept
  419. {
  420. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  421. return pData->dspLoad;
  422. #else
  423. return 0.0f;
  424. #endif
  425. }
  426. uint32_t CarlaEngine::getTotalXruns() const noexcept
  427. {
  428. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  429. return pData->xruns;
  430. #else
  431. return 0;
  432. #endif
  433. }
  434. void CarlaEngine::clearXruns() const noexcept
  435. {
  436. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  437. pData->xruns = 0;
  438. #endif
  439. }
  440. bool CarlaEngine::showDeviceControlPanel() const noexcept
  441. {
  442. return false;
  443. }
  444. bool CarlaEngine::setBufferSizeAndSampleRate(const uint, const double)
  445. {
  446. return false;
  447. }
  448. // -----------------------------------------------------------------------
  449. // Plugin management
  450. bool CarlaEngine::addPlugin(const BinaryType btype,
  451. const PluginType ptype,
  452. const char* const filename,
  453. const char* const name,
  454. const char* const label,
  455. const int64_t uniqueId,
  456. const void* const extra,
  457. const uint options)
  458. {
  459. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  460. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  461. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  462. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextPluginId <= pData->maxPluginNumber, "Invalid engine internal data");
  463. #endif
  464. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  465. CARLA_SAFE_ASSERT_RETURN_ERR(btype != BINARY_NONE, "Invalid plugin binary mode");
  466. CARLA_SAFE_ASSERT_RETURN_ERR(ptype != PLUGIN_NONE, "Invalid plugin type");
  467. CARLA_SAFE_ASSERT_RETURN_ERR((filename != nullptr && filename[0] != '\0') || (label != nullptr && label[0] != '\0'), "Invalid plugin filename and label");
  468. carla_debug("CarlaEngine::addPlugin(%i:%s, %i:%s, \"%s\", \"%s\", \"%s\", " P_INT64 ", %p, %u)",
  469. btype, BinaryType2Str(btype), ptype, PluginType2Str(ptype), filename, name, label, uniqueId, extra, options);
  470. #ifndef CARLA_OS_WIN
  471. if (ptype != PLUGIN_JACK && ptype != PLUGIN_LV2 && filename != nullptr && filename[0] != '\0') {
  472. CARLA_SAFE_ASSERT_RETURN_ERR(filename[0] == CARLA_OS_SEP || filename[0] == '.' || filename[0] == '~', "Invalid plugin filename");
  473. }
  474. #endif
  475. uint id;
  476. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  477. CarlaPluginPtr oldPlugin;
  478. if (pData->nextPluginId < pData->curPluginCount)
  479. {
  480. id = pData->nextPluginId;
  481. pData->nextPluginId = pData->maxPluginNumber;
  482. oldPlugin = pData->plugins[id].plugin;
  483. CARLA_SAFE_ASSERT_RETURN_ERR(oldPlugin.get() != nullptr, "Invalid replace plugin Id");
  484. }
  485. else
  486. #endif
  487. {
  488. id = pData->curPluginCount;
  489. if (id == pData->maxPluginNumber)
  490. {
  491. setLastError("Maximum number of plugins reached");
  492. return false;
  493. }
  494. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  495. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins[id].plugin.get() == nullptr, "Invalid engine internal data");
  496. #endif
  497. }
  498. CarlaPlugin::Initializer initializer = {
  499. this,
  500. id,
  501. filename,
  502. name,
  503. label,
  504. uniqueId,
  505. options
  506. };
  507. CarlaPluginPtr plugin;
  508. CarlaString bridgeBinary(pData->options.binaryDir);
  509. if (bridgeBinary.isNotEmpty())
  510. {
  511. #ifndef CARLA_OS_WIN
  512. if (btype == BINARY_NATIVE)
  513. {
  514. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-native";
  515. }
  516. else
  517. #endif
  518. {
  519. switch (btype)
  520. {
  521. case BINARY_POSIX32:
  522. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-posix32";
  523. break;
  524. case BINARY_POSIX64:
  525. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-posix64";
  526. break;
  527. case BINARY_WIN32:
  528. #if defined(CARLA_OS_WIN) && !defined(CARLA_OS_64BIT)
  529. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-native.exe";
  530. #else
  531. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-win32.exe";
  532. #endif
  533. break;
  534. case BINARY_WIN64:
  535. #if defined(CARLA_OS_WIN) && defined(CARLA_OS_64BIT)
  536. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-native.exe";
  537. #else
  538. bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-win64.exe";
  539. #endif
  540. break;
  541. default:
  542. bridgeBinary.clear();
  543. break;
  544. }
  545. }
  546. if (! File(bridgeBinary.buffer()).existsAsFile())
  547. bridgeBinary.clear();
  548. }
  549. const bool canBeBridged = ptype != PLUGIN_INTERNAL
  550. && ptype != PLUGIN_DLS
  551. && ptype != PLUGIN_GIG
  552. && ptype != PLUGIN_SF2
  553. && ptype != PLUGIN_SFZ
  554. && ptype != PLUGIN_JSFX
  555. && ptype != PLUGIN_JACK;
  556. // Prefer bridges for some specific plugins
  557. bool preferBridges = pData->options.preferPluginBridges;
  558. const char* needsArchBridge = nullptr;
  559. #ifdef CARLA_OS_MAC
  560. // Plugin might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
  561. if (canBeBridged && ptype != PLUGIN_LV2 && ptype != PLUGIN_AU)
  562. removeFileFromQuarantine(filename);
  563. #endif
  564. #ifndef BUILD_BRIDGE
  565. if (canBeBridged && ! preferBridges)
  566. {
  567. /*
  568. if (ptype == PLUGIN_LV2 && label != nullptr)
  569. {
  570. if (std::strncmp(label, "http://calf.sourceforge.net/plugins/", 36) == 0 ||
  571. std::strcmp(label, "http://factorial.hu/plugins/lv2/ir") == 0 ||
  572. std::strstr(label, "v1.sourceforge.net/lv2") != nullptr)
  573. {
  574. preferBridges = true;
  575. }
  576. }
  577. */
  578. #ifdef ADAPT_FOR_APPLE_SILLICON
  579. // see if this binary needs bridging
  580. if (ptype == PLUGIN_VST2 || ptype == PLUGIN_VST3)
  581. {
  582. if (const char* const vst2Binary = findBinaryInBundle(filename))
  583. {
  584. const CarlaMagic magic;
  585. if (const char* const output = magic.getFileDescription(vst2Binary))
  586. {
  587. carla_stdout("VST binary magic output is '%s'", output);
  588. #ifdef __aarch64__
  589. if (std::strstr(output, "arm64") == nullptr && std::strstr(output, "x86_64") != nullptr)
  590. needsArchBridge = "x86_64";
  591. #else
  592. if (std::strstr(output, "x86_64") == nullptr && std::strstr(output, "arm64") != nullptr)
  593. needsArchBridge = "arm64";
  594. #endif
  595. }
  596. else
  597. {
  598. carla_stdout("VST binary magic output is null");
  599. }
  600. }
  601. else
  602. {
  603. carla_stdout("Search for binary in VST bundle failed");
  604. }
  605. }
  606. #endif // ADAPT_FOR_APPLE_SILLICON
  607. }
  608. #endif // ! BUILD_BRIDGE
  609. #if defined(CARLA_PLUGIN_ONLY_BRIDGE)
  610. if (bridgeBinary.isNotEmpty())
  611. {
  612. plugin = CarlaPlugin::newBridge(initializer, btype, ptype, needsArchBridge, bridgeBinary);
  613. }
  614. else
  615. {
  616. setLastError("Cannot load plugin, the required plugin bridge is not available");
  617. return false;
  618. }
  619. #elif !defined(CARLA_OS_WASM)
  620. if (canBeBridged && (needsArchBridge || btype != BINARY_NATIVE || (preferBridges && bridgeBinary.isNotEmpty())))
  621. {
  622. if (bridgeBinary.isNotEmpty())
  623. {
  624. plugin = CarlaPlugin::newBridge(initializer, btype, ptype, needsArchBridge, bridgeBinary);
  625. }
  626. else
  627. {
  628. setLastError("This Carla build cannot handle this binary");
  629. return false;
  630. }
  631. }
  632. else
  633. #endif
  634. #ifndef CARLA_PLUGIN_ONLY_BRIDGE
  635. {
  636. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  637. bool use16Outs;
  638. #endif
  639. setLastError("Invalid or unsupported plugin type");
  640. // Some stupid plugins mess up with global signals, err!!
  641. const CarlaSignalRestorer csr;
  642. switch (ptype)
  643. {
  644. case PLUGIN_NONE:
  645. case PLUGIN_TYPE_COUNT:
  646. break;
  647. case PLUGIN_LADSPA:
  648. plugin = CarlaPlugin::newLADSPA(initializer, (const LADSPA_RDF_Descriptor*)extra);
  649. break;
  650. case PLUGIN_DSSI:
  651. plugin = CarlaPlugin::newDSSI(initializer);
  652. break;
  653. case PLUGIN_LV2:
  654. plugin = CarlaPlugin::newLV2(initializer);
  655. break;
  656. case PLUGIN_VST2:
  657. plugin = CarlaPlugin::newVST2(initializer);
  658. break;
  659. case PLUGIN_VST3:
  660. plugin = CarlaPlugin::newVST3(initializer);
  661. break;
  662. case PLUGIN_AU:
  663. plugin = CarlaPlugin::newAU(initializer);
  664. break;
  665. case PLUGIN_CLAP:
  666. plugin = CarlaPlugin::newCLAP(initializer);
  667. break;
  668. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  669. case PLUGIN_INTERNAL:
  670. plugin = CarlaPlugin::newNative(initializer);
  671. break;
  672. case PLUGIN_DLS:
  673. case PLUGIN_GIG:
  674. case PLUGIN_SF2:
  675. use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
  676. plugin = CarlaPlugin::newFluidSynth(initializer, ptype, use16Outs);
  677. break;
  678. case PLUGIN_SFZ:
  679. #ifdef SFZ_FILES_USING_SFIZZ
  680. {
  681. CarlaPlugin::Initializer sfizzInitializer = {
  682. this,
  683. id,
  684. name,
  685. "",
  686. "http://sfztools.github.io/sfizz",
  687. 0,
  688. options
  689. };
  690. plugin = CarlaPlugin::newLV2(sfizzInitializer);
  691. }
  692. #else
  693. plugin = CarlaPlugin::newSFZero(initializer);
  694. #endif
  695. break;
  696. case PLUGIN_JSFX:
  697. plugin = CarlaPlugin::newJSFX(initializer);
  698. break;
  699. case PLUGIN_JACK:
  700. #ifdef HAVE_JACK
  701. plugin = CarlaPlugin::newJackApp(initializer);
  702. #else
  703. setLastError("JACK plugin target is not available");
  704. #endif
  705. break;
  706. #else
  707. case PLUGIN_INTERNAL:
  708. case PLUGIN_DLS:
  709. case PLUGIN_GIG:
  710. case PLUGIN_SF2:
  711. case PLUGIN_SFZ:
  712. case PLUGIN_JACK:
  713. case PLUGIN_JSFX:
  714. setLastError("Plugin bridges cannot handle this binary");
  715. break;
  716. #endif // BUILD_BRIDGE_ALTERNATIVE_ARCH
  717. }
  718. }
  719. #endif // CARLA_PLUGIN_ONLY_BRIDGE
  720. if (plugin.get() == nullptr)
  721. return false;
  722. plugin->reload();
  723. #ifdef SFZ_FILES_USING_SFIZZ
  724. if (ptype == PLUGIN_SFZ && plugin->getType() == PLUGIN_LV2)
  725. {
  726. plugin->setCustomData(LV2_ATOM__Path,
  727. "http://sfztools.github.io/sfizz:sfzfile",
  728. filename,
  729. false);
  730. plugin->restoreLV2State(true);
  731. }
  732. #endif
  733. bool canRun = true;
  734. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  735. {
  736. /**/ if (plugin->getMidiInCount() > 1 || plugin->getMidiOutCount() > 1)
  737. {
  738. setLastError("Carla's patchbay mode cannot work with plugins that have multiple MIDI ports, sorry!");
  739. canRun = false;
  740. }
  741. }
  742. if (! canRun)
  743. {
  744. return false;
  745. }
  746. EnginePluginData& pluginData(pData->plugins[id]);
  747. pluginData.plugin = plugin;
  748. carla_zeroFloats(pluginData.peaks, 4);
  749. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  750. if (oldPlugin.get() != nullptr)
  751. {
  752. CARLA_SAFE_ASSERT(! pData->loadingProject);
  753. const ScopedRunnerStopper srs(this);
  754. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  755. pData->graph.replacePlugin(oldPlugin, plugin);
  756. const bool wasActive = oldPlugin->getInternalParameterValue(PARAMETER_ACTIVE) >= 0.5f;
  757. const float oldDryWet = oldPlugin->getInternalParameterValue(PARAMETER_DRYWET);
  758. const float oldVolume = oldPlugin->getInternalParameterValue(PARAMETER_VOLUME);
  759. oldPlugin->prepareForDeletion();
  760. {
  761. const CarlaMutexLocker cml(pData->pluginsToDeleteMutex);
  762. pData->pluginsToDelete.push_back(oldPlugin);
  763. }
  764. if (plugin->getHints() & PLUGIN_CAN_DRYWET)
  765. plugin->setDryWet(oldDryWet, true, true);
  766. if (plugin->getHints() & PLUGIN_CAN_VOLUME)
  767. plugin->setVolume(oldVolume, true, true);
  768. plugin->setActive(wasActive, true, true);
  769. plugin->setEnabled(true);
  770. callback(true, true, ENGINE_CALLBACK_RELOAD_ALL, id, 0, 0, 0, 0.0f, nullptr);
  771. }
  772. else if (! pData->loadingProject)
  773. #endif
  774. {
  775. plugin->setEnabled(true);
  776. ++pData->curPluginCount;
  777. callback(true, true, ENGINE_CALLBACK_PLUGIN_ADDED, id, plugin->getType(), 0, 0, 0.0f, plugin->getName());
  778. if (getType() != kEngineTypeBridge)
  779. plugin->setActive(true, true, true);
  780. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  781. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  782. pData->graph.addPlugin(plugin);
  783. #endif
  784. }
  785. return true;
  786. #if defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) || defined(CARLA_PLUGIN_ONLY_BRIDGE)
  787. // unused
  788. (void)extra;
  789. #endif
  790. }
  791. bool CarlaEngine::addPlugin(const PluginType ptype,
  792. const char* const filename,
  793. const char* const name,
  794. const char* const label,
  795. const int64_t uniqueId,
  796. const void* const extra)
  797. {
  798. return addPlugin(BINARY_NATIVE, ptype, filename, name, label, uniqueId, extra, PLUGIN_OPTIONS_NULL);
  799. }
  800. bool CarlaEngine::removePlugin(const uint id)
  801. {
  802. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  803. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  804. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  805. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data");
  806. #else
  807. CARLA_SAFE_ASSERT_RETURN_ERR(id == 0, "Invalid engine internal data");
  808. #endif
  809. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  810. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id");
  811. carla_debug("CarlaEngine::removePlugin(%i)", id);
  812. const CarlaPluginPtr plugin = pData->plugins[id].plugin;
  813. CARLA_SAFE_ASSERT_RETURN_ERR(plugin.get() != nullptr, "Could not find plugin to remove");
  814. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data");
  815. const ScopedRunnerStopper srs(this);
  816. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  817. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  818. pData->graph.removePlugin(plugin);
  819. const ScopedActionLock sal(this, kEnginePostActionRemovePlugin, id, 0);
  820. /*
  821. for (uint i=id; i < pData->curPluginCount; ++i)
  822. {
  823. CarlaPlugin* const plugin2(pData->plugins[i].plugin);
  824. CARLA_SAFE_ASSERT_BREAK(plugin2 != nullptr);
  825. plugin2->updateOscURL();
  826. }
  827. */
  828. #else
  829. pData->curPluginCount = 0;
  830. pData->plugins[0].plugin.reset();
  831. carla_zeroStruct(pData->plugins[0].peaks);
  832. #endif
  833. plugin->prepareForDeletion();
  834. {
  835. const CarlaMutexLocker cml(pData->pluginsToDeleteMutex);
  836. pData->pluginsToDelete.push_back(plugin);
  837. }
  838. callback(true, true, ENGINE_CALLBACK_PLUGIN_REMOVED, id, 0, 0, 0, 0.0f, nullptr);
  839. return true;
  840. }
  841. bool CarlaEngine::removeAllPlugins()
  842. {
  843. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  844. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  845. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  846. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextPluginId == pData->maxPluginNumber, "Invalid engine internal data");
  847. #endif
  848. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  849. carla_debug("CarlaEngine::removeAllPlugins()");
  850. if (pData->curPluginCount == 0)
  851. return true;
  852. const ScopedRunnerStopper srs(this);
  853. const uint curPluginCount = pData->curPluginCount;
  854. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  855. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  856. pData->graph.removeAllPlugins(pData->aboutToClose);
  857. #endif
  858. const ScopedActionLock sal(this, kEnginePostActionZeroCount, 0, 0);
  859. callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  860. for (uint i=0; i < curPluginCount; ++i)
  861. {
  862. const uint id = curPluginCount - i - 1;
  863. EnginePluginData& pluginData(pData->plugins[id]);
  864. pluginData.plugin->prepareForDeletion();
  865. {
  866. const CarlaMutexLocker cml(pData->pluginsToDeleteMutex);
  867. pData->pluginsToDelete.push_back(pluginData.plugin);
  868. }
  869. pluginData.plugin.reset();
  870. carla_zeroStruct(pluginData.peaks);
  871. callback(true, true, ENGINE_CALLBACK_PLUGIN_REMOVED, id, 0, 0, 0, 0.0f, nullptr);
  872. callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  873. }
  874. return true;
  875. }
  876. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  877. bool CarlaEngine::renamePlugin(const uint id, const char* const newName)
  878. {
  879. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  880. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  881. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data");
  882. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  883. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id");
  884. CARLA_SAFE_ASSERT_RETURN_ERR(newName != nullptr && newName[0] != '\0', "Invalid plugin name");
  885. carla_debug("CarlaEngine::renamePlugin(%i, \"%s\")", id, newName);
  886. const CarlaPluginPtr plugin = pData->plugins[id].plugin;
  887. CARLA_SAFE_ASSERT_RETURN_ERR(plugin.get() != nullptr, "Could not find plugin to rename");
  888. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data");
  889. const char* const uniqueName(getUniquePluginName(newName));
  890. CARLA_SAFE_ASSERT_RETURN_ERR(uniqueName != nullptr, "Unable to get new unique plugin name");
  891. plugin->setName(uniqueName);
  892. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  893. pData->graph.renamePlugin(plugin, uniqueName);
  894. callback(true, true, ENGINE_CALLBACK_PLUGIN_RENAMED, id, 0, 0, 0, 0.0f, uniqueName);
  895. delete[] uniqueName;
  896. return true;
  897. }
  898. bool CarlaEngine::clonePlugin(const uint id)
  899. {
  900. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  901. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  902. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data");
  903. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  904. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id");
  905. carla_debug("CarlaEngine::clonePlugin(%i)", id);
  906. const CarlaPluginPtr plugin = pData->plugins[id].plugin;
  907. CARLA_SAFE_ASSERT_RETURN_ERR(plugin.get() != nullptr, "Could not find plugin to clone");
  908. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data");
  909. char label[STR_MAX+1];
  910. carla_zeroChars(label, STR_MAX+1);
  911. if (! plugin->getLabel(label))
  912. label[0] = '\0';
  913. const uint pluginCountBefore(pData->curPluginCount);
  914. if (! addPlugin(plugin->getBinaryType(), plugin->getType(),
  915. plugin->getFilename(), plugin->getName(), label, plugin->getUniqueId(),
  916. plugin->getExtraStuff(), plugin->getOptionsEnabled()))
  917. return false;
  918. CARLA_SAFE_ASSERT_RETURN_ERR(pluginCountBefore+1 == pData->curPluginCount, "No new plugin found");
  919. if (const CarlaPluginPtr newPlugin = pData->plugins[pluginCountBefore].plugin)
  920. {
  921. if (newPlugin->getType() == PLUGIN_LV2)
  922. newPlugin->cloneLV2Files(*plugin);
  923. newPlugin->loadStateSave(plugin->getStateSave(true));
  924. }
  925. return true;
  926. }
  927. bool CarlaEngine::replacePlugin(const uint id) noexcept
  928. {
  929. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  930. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  931. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount != 0, "Invalid engine internal data");
  932. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  933. carla_debug("CarlaEngine::replacePlugin(%i)", id);
  934. // might use this to reset
  935. if (id == pData->maxPluginNumber)
  936. {
  937. pData->nextPluginId = pData->maxPluginNumber;
  938. return true;
  939. }
  940. CARLA_SAFE_ASSERT_RETURN_ERR(id < pData->curPluginCount, "Invalid plugin Id");
  941. const CarlaPluginPtr plugin = pData->plugins[id].plugin;
  942. CARLA_SAFE_ASSERT_RETURN_ERR(plugin.get() != nullptr, "Could not find plugin to replace");
  943. CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data");
  944. pData->nextPluginId = id;
  945. return true;
  946. }
  947. bool CarlaEngine::switchPlugins(const uint idA, const uint idB) noexcept
  948. {
  949. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  950. CARLA_SAFE_ASSERT_RETURN_ERR(pData->plugins != nullptr, "Invalid engine internal data");
  951. CARLA_SAFE_ASSERT_RETURN_ERR(pData->curPluginCount >= 2, "Invalid engine internal data");
  952. CARLA_SAFE_ASSERT_RETURN_ERR(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  953. CARLA_SAFE_ASSERT_RETURN_ERR(idA != idB, "Invalid operation, cannot switch plugin with itself");
  954. CARLA_SAFE_ASSERT_RETURN_ERR(idA < pData->curPluginCount, "Invalid plugin Id");
  955. CARLA_SAFE_ASSERT_RETURN_ERR(idB < pData->curPluginCount, "Invalid plugin Id");
  956. carla_debug("CarlaEngine::switchPlugins(%i)", idA, idB);
  957. const CarlaPluginPtr pluginA = pData->plugins[idA].plugin;
  958. const CarlaPluginPtr pluginB = pData->plugins[idB].plugin;
  959. CARLA_SAFE_ASSERT_RETURN_ERR(pluginA.get() != nullptr, "Could not find plugin to switch");
  960. CARLA_SAFE_ASSERT_RETURN_ERR(pluginB.get() != nullptr, "Could not find plugin to switch");
  961. CARLA_SAFE_ASSERT_RETURN_ERR(pluginA->getId() == idA, "Invalid engine internal data");
  962. CARLA_SAFE_ASSERT_RETURN_ERR(pluginB->getId() == idB, "Invalid engine internal data");
  963. const ScopedRunnerStopper srs(this);
  964. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  965. pData->graph.switchPlugins(pluginA, pluginB);
  966. const ScopedActionLock sal(this, kEnginePostActionSwitchPlugins, idA, idB);
  967. // TODO
  968. /*
  969. pluginA->updateOscURL();
  970. pluginB->updateOscURL();
  971. if (isOscControlRegistered())
  972. oscSend_control_switch_plugins(idA, idB);
  973. */
  974. return true;
  975. }
  976. #endif
  977. void CarlaEngine::touchPluginParameter(const uint, const uint32_t, const bool) noexcept
  978. {
  979. }
  980. CarlaPluginPtr CarlaEngine::getPlugin(const uint id) const noexcept
  981. {
  982. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  983. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->plugins != nullptr, "Invalid engine internal data");
  984. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->curPluginCount != 0, "Invalid engine internal data");
  985. #endif
  986. CARLA_SAFE_ASSERT_RETURN_ERRN(pData->nextAction.opcode == kEnginePostActionNull, "Invalid engine internal data");
  987. CARLA_SAFE_ASSERT_RETURN_ERRN(id < pData->curPluginCount, "Invalid plugin Id");
  988. return pData->plugins[id].plugin;
  989. }
  990. CarlaPluginPtr CarlaEngine::getPluginUnchecked(const uint id) const noexcept
  991. {
  992. return pData->plugins[id].plugin;
  993. }
  994. const char* CarlaEngine::getUniquePluginName(const char* const name) const
  995. {
  996. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull, nullptr);
  997. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr);
  998. carla_debug("CarlaEngine::getUniquePluginName(\"%s\")", name);
  999. CarlaString sname;
  1000. sname = name;
  1001. if (sname.isEmpty())
  1002. {
  1003. sname = "(No name)";
  1004. return sname.dup();
  1005. }
  1006. const std::size_t maxNameSize(carla_minConstrained<uint>(getMaxClientNameSize(), 0xff, 6U) - 6); // 6 = strlen(" (10)") + 1
  1007. if (maxNameSize == 0 || ! isRunning())
  1008. return sname.dup();
  1009. sname.truncate(maxNameSize);
  1010. sname.replace(':', '.'); // ':' is used in JACK1 to split client/port names
  1011. sname.replace('/', '.'); // '/' is used by us for client name prefix
  1012. for (uint i=0; i < pData->curPluginCount; ++i)
  1013. {
  1014. const CarlaPluginPtr plugin = pData->plugins[i].plugin;
  1015. CARLA_SAFE_ASSERT_BREAK(plugin.use_count() > 0);
  1016. // Check if unique name doesn't exist
  1017. if (const char* const pluginName = plugin->getName())
  1018. {
  1019. if (sname != pluginName)
  1020. continue;
  1021. }
  1022. // Check if string has already been modified
  1023. {
  1024. const std::size_t len(sname.length());
  1025. // 1 digit, ex: " (2)"
  1026. if (len > 4 && sname[len-4] == ' ' && sname[len-3] == '(' && sname.isDigit(len-2) && sname[len-1] == ')')
  1027. {
  1028. const int number = sname[len-2] - '0';
  1029. if (number == 9)
  1030. {
  1031. // next number is 10, 2 digits
  1032. sname.truncate(len-4);
  1033. sname += " (10)";
  1034. //sname.replace(" (9)", " (10)");
  1035. }
  1036. else
  1037. sname[len-2] = char('0' + number + 1);
  1038. continue;
  1039. }
  1040. // 2 digits, ex: " (11)"
  1041. if (len > 5 && sname[len-5] == ' ' && sname[len-4] == '(' && sname.isDigit(len-3) && sname.isDigit(len-2) && sname[len-1] == ')')
  1042. {
  1043. char n2 = sname[len-2];
  1044. char n3 = sname[len-3];
  1045. if (n2 == '9')
  1046. {
  1047. n2 = '0';
  1048. n3 = static_cast<char>(n3 + 1);
  1049. }
  1050. else
  1051. n2 = static_cast<char>(n2 + 1);
  1052. sname[len-2] = n2;
  1053. sname[len-3] = n3;
  1054. continue;
  1055. }
  1056. }
  1057. // Modify string if not
  1058. sname += " (2)";
  1059. }
  1060. return sname.dup();
  1061. }
  1062. // -----------------------------------------------------------------------
  1063. // Project management
  1064. bool CarlaEngine::loadFile(const char* const filename)
  1065. {
  1066. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  1067. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename");
  1068. carla_debug("CarlaEngine::loadFile(\"%s\")", filename);
  1069. const String jfilename = String(CharPointer_UTF8(filename));
  1070. File file(jfilename);
  1071. CARLA_SAFE_ASSERT_RETURN_ERR(file.exists(), "Requested file does not exist or is not a readable");
  1072. CarlaString baseName(file.getFileNameWithoutExtension().toRawUTF8());
  1073. CarlaString extension(file.getFileExtension().replace(".","").toLowerCase().toRawUTF8());
  1074. const uint curPluginId(pData->nextPluginId < pData->curPluginCount ? pData->nextPluginId : pData->curPluginCount);
  1075. // -------------------------------------------------------------------
  1076. // NOTE: please keep in sync with carla_get_supported_file_extensions!!
  1077. if (extension == "carxp" || extension == "carxs")
  1078. return loadProject(filename, false);
  1079. // -------------------------------------------------------------------
  1080. if (extension == "dls")
  1081. return addPlugin(PLUGIN_DLS, filename, baseName, baseName, 0, nullptr);
  1082. if (extension == "gig")
  1083. return addPlugin(PLUGIN_GIG, filename, baseName, baseName, 0, nullptr);
  1084. if (extension == "sf2" || extension == "sf3")
  1085. return addPlugin(PLUGIN_SF2, filename, baseName, baseName, 0, nullptr);
  1086. if (extension == "sfz")
  1087. return addPlugin(PLUGIN_SFZ, filename, baseName, baseName, 0, nullptr);
  1088. if (extension == "jsfx")
  1089. return addPlugin(PLUGIN_JSFX, filename, baseName, baseName, 0, nullptr);
  1090. // -------------------------------------------------------------------
  1091. if (
  1092. extension == "mp3" ||
  1093. #ifdef HAVE_SNDFILE
  1094. extension == "aif" ||
  1095. extension == "aifc" ||
  1096. extension == "aiff" ||
  1097. extension == "au" ||
  1098. extension == "bwf" ||
  1099. extension == "flac" ||
  1100. extension == "htk" ||
  1101. extension == "iff" ||
  1102. extension == "mat4" ||
  1103. extension == "mat5" ||
  1104. extension == "oga" ||
  1105. extension == "ogg" ||
  1106. extension == "opus" ||
  1107. extension == "paf" ||
  1108. extension == "pvf" ||
  1109. extension == "pvf5" ||
  1110. extension == "sd2" ||
  1111. extension == "sf" ||
  1112. extension == "snd" ||
  1113. extension == "svx" ||
  1114. extension == "vcc" ||
  1115. extension == "w64" ||
  1116. extension == "wav" ||
  1117. extension == "xi" ||
  1118. #endif
  1119. #ifdef HAVE_FFMPEG
  1120. extension == "3g2" ||
  1121. extension == "3gp" ||
  1122. extension == "aac" ||
  1123. extension == "ac3" ||
  1124. extension == "amr" ||
  1125. extension == "ape" ||
  1126. extension == "mp2" ||
  1127. extension == "mpc" ||
  1128. extension == "wma" ||
  1129. # ifndef HAVE_SNDFILE
  1130. // FFmpeg without sndfile
  1131. extension == "flac" ||
  1132. extension == "oga" ||
  1133. extension == "ogg" ||
  1134. extension == "w64" ||
  1135. extension == "wav" ||
  1136. # endif
  1137. #endif
  1138. false
  1139. )
  1140. {
  1141. if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "audiofile", 0, nullptr))
  1142. {
  1143. if (const CarlaPluginPtr plugin = getPlugin(curPluginId))
  1144. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "file", filename, true);
  1145. return true;
  1146. }
  1147. return false;
  1148. }
  1149. // -------------------------------------------------------------------
  1150. if (extension == "mid" || extension == "midi")
  1151. {
  1152. if (addPlugin(PLUGIN_INTERNAL, nullptr, baseName, "midifile", 0, nullptr))
  1153. {
  1154. if (const CarlaPluginPtr plugin = getPlugin(curPluginId))
  1155. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "file", filename, true);
  1156. return true;
  1157. }
  1158. return false;
  1159. }
  1160. // -------------------------------------------------------------------
  1161. // ZynAddSubFX
  1162. if (extension == "xmz" || extension == "xiz")
  1163. {
  1164. #ifdef HAVE_ZYN_DEPS
  1165. CarlaString nicerName("Zyn - ");
  1166. const std::size_t sep(baseName.find('-')+1);
  1167. if (sep < baseName.length())
  1168. nicerName += baseName.buffer()+sep;
  1169. else
  1170. nicerName += baseName;
  1171. if (addPlugin(PLUGIN_INTERNAL, nullptr, nicerName, "zynaddsubfx", 0, nullptr))
  1172. {
  1173. callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, curPluginId, 0, 0, 0, 0.0f, nullptr);
  1174. if (const CarlaPluginPtr plugin = getPlugin(curPluginId))
  1175. {
  1176. const char* const ext = (extension == "xmz") ? "CarlaAlternateFile1" : "CarlaAlternateFile2";
  1177. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, ext, filename, true);
  1178. }
  1179. return true;
  1180. }
  1181. return false;
  1182. #else
  1183. setLastError("This Carla build does not have ZynAddSubFX support");
  1184. return false;
  1185. #endif
  1186. }
  1187. // -------------------------------------------------------------------
  1188. // Direct plugin binaries
  1189. #ifdef CARLA_OS_MAC
  1190. if (extension == "vst")
  1191. return addPlugin(PLUGIN_VST2, filename, nullptr, nullptr, 0, nullptr);
  1192. #else
  1193. if (extension == "dll" || extension == "so")
  1194. return addPlugin(getBinaryTypeFromFile(filename), PLUGIN_VST2, filename, nullptr, nullptr, 0, nullptr);
  1195. #endif
  1196. if (extension == "vst3")
  1197. return addPlugin(getBinaryTypeFromFile(filename), PLUGIN_VST3, filename, nullptr, nullptr, 0, nullptr);
  1198. if (extension == "clap")
  1199. return addPlugin(getBinaryTypeFromFile(filename), PLUGIN_CLAP, filename, nullptr, nullptr, 0, nullptr);
  1200. // -------------------------------------------------------------------
  1201. setLastError("Unknown file extension");
  1202. return false;
  1203. }
  1204. bool CarlaEngine::loadProject(const char* const filename, const bool setAsCurrentProject)
  1205. {
  1206. CARLA_SAFE_ASSERT_RETURN_ERR(pData->isIdling == 0, "An operation is still being processed, please wait for it to finish");
  1207. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename");
  1208. carla_debug("CarlaEngine::loadProject(\"%s\")", filename);
  1209. const String jfilename = String(CharPointer_UTF8(filename));
  1210. const File file(jfilename);
  1211. CARLA_SAFE_ASSERT_RETURN_ERR(file.existsAsFile(), "Requested file does not exist or is not a readable file");
  1212. if (setAsCurrentProject)
  1213. {
  1214. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1215. if (pData->currentProjectFilename != filename)
  1216. {
  1217. pData->currentProjectFilename = filename;
  1218. bool found;
  1219. const size_t r = pData->currentProjectFilename.rfind(CARLA_OS_SEP, &found);
  1220. if (found)
  1221. {
  1222. pData->currentProjectFolder = filename;
  1223. pData->currentProjectFolder[r] = '\0';
  1224. }
  1225. else
  1226. {
  1227. pData->currentProjectFolder.clear();
  1228. }
  1229. }
  1230. #endif
  1231. }
  1232. XmlDocument xml(file);
  1233. return loadProjectInternal(xml, !setAsCurrentProject);
  1234. }
  1235. bool CarlaEngine::saveProject(const char* const filename, const bool setAsCurrentProject)
  1236. {
  1237. CARLA_SAFE_ASSERT_RETURN_ERR(filename != nullptr && filename[0] != '\0', "Invalid filename");
  1238. carla_debug("CarlaEngine::saveProject(\"%s\")", filename);
  1239. if (setAsCurrentProject)
  1240. {
  1241. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1242. if (pData->currentProjectFilename != filename)
  1243. {
  1244. pData->currentProjectFilename = filename;
  1245. bool found;
  1246. const size_t r = pData->currentProjectFilename.rfind(CARLA_OS_SEP, &found);
  1247. if (found)
  1248. {
  1249. pData->currentProjectFolder = filename;
  1250. pData->currentProjectFolder[r] = '\0';
  1251. }
  1252. else
  1253. {
  1254. pData->currentProjectFolder.clear();
  1255. }
  1256. }
  1257. #endif
  1258. }
  1259. MemoryOutputStream out;
  1260. saveProjectInternal(out);
  1261. const String jfilename = String(CharPointer_UTF8(filename));
  1262. File file(jfilename);
  1263. if (file.replaceWithData(out.getData(), out.getDataSize()))
  1264. return true;
  1265. setLastError("Failed to write file");
  1266. return false;
  1267. }
  1268. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1269. const char* CarlaEngine::getCurrentProjectFolder() const noexcept
  1270. {
  1271. return pData->currentProjectFolder.isNotEmpty() ? pData->currentProjectFolder.buffer()
  1272. : nullptr;
  1273. }
  1274. const char* CarlaEngine::getCurrentProjectFilename() const noexcept
  1275. {
  1276. return pData->currentProjectFilename;
  1277. }
  1278. void CarlaEngine::clearCurrentProjectFilename() noexcept
  1279. {
  1280. pData->currentProjectFilename.clear();
  1281. pData->currentProjectFolder.clear();
  1282. }
  1283. #endif
  1284. // -----------------------------------------------------------------------
  1285. // Information (base)
  1286. uint32_t CarlaEngine::getBufferSize() const noexcept
  1287. {
  1288. return pData->bufferSize;
  1289. }
  1290. double CarlaEngine::getSampleRate() const noexcept
  1291. {
  1292. return pData->sampleRate;
  1293. }
  1294. const char* CarlaEngine::getName() const noexcept
  1295. {
  1296. return pData->name;
  1297. }
  1298. EngineProcessMode CarlaEngine::getProccessMode() const noexcept
  1299. {
  1300. return pData->options.processMode;
  1301. }
  1302. const EngineOptions& CarlaEngine::getOptions() const noexcept
  1303. {
  1304. return pData->options;
  1305. }
  1306. EngineTimeInfo CarlaEngine::getTimeInfo() const noexcept
  1307. {
  1308. return pData->timeInfo;
  1309. }
  1310. // -----------------------------------------------------------------------
  1311. // Information (peaks)
  1312. const float* CarlaEngine::getPeaks(const uint pluginId) const noexcept
  1313. {
  1314. static const float kFallback[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  1315. if (pluginId == MAIN_CARLA_PLUGIN_ID)
  1316. {
  1317. // get peak from first plugin, if available
  1318. if (const uint count = pData->curPluginCount)
  1319. {
  1320. pData->peaks[0] = pData->plugins[0].peaks[0];
  1321. pData->peaks[1] = pData->plugins[0].peaks[1];
  1322. pData->peaks[2] = pData->plugins[count-1].peaks[2];
  1323. pData->peaks[3] = pData->plugins[count-1].peaks[3];
  1324. }
  1325. else
  1326. {
  1327. carla_zeroFloats(pData->peaks, 4);
  1328. }
  1329. return pData->peaks;
  1330. }
  1331. CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, kFallback);
  1332. return pData->plugins[pluginId].peaks;
  1333. }
  1334. float CarlaEngine::getInputPeak(const uint pluginId, const bool isLeft) const noexcept
  1335. {
  1336. if (pluginId == MAIN_CARLA_PLUGIN_ID)
  1337. {
  1338. // get peak from first plugin, if available
  1339. if (pData->curPluginCount > 0)
  1340. return pData->plugins[0].peaks[isLeft ? 0 : 1];
  1341. return 0.0f;
  1342. }
  1343. CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, 0.0f);
  1344. return pData->plugins[pluginId].peaks[isLeft ? 0 : 1];
  1345. }
  1346. float CarlaEngine::getOutputPeak(const uint pluginId, const bool isLeft) const noexcept
  1347. {
  1348. if (pluginId == MAIN_CARLA_PLUGIN_ID)
  1349. {
  1350. // get peak from last plugin, if available
  1351. if (pData->curPluginCount > 0)
  1352. return pData->plugins[pData->curPluginCount-1].peaks[isLeft ? 2 : 3];
  1353. return 0.0f;
  1354. }
  1355. CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount, 0.0f);
  1356. return pData->plugins[pluginId].peaks[isLeft ? 2 : 3];
  1357. }
  1358. // -----------------------------------------------------------------------
  1359. // Callback
  1360. void CarlaEngine::callback(const bool sendHost, const bool sendOSC,
  1361. const EngineCallbackOpcode action, const uint pluginId,
  1362. const int value1, const int value2, const int value3,
  1363. const float valuef, const char* const valueStr) noexcept
  1364. {
  1365. #ifdef DEBUG
  1366. if (pData->isIdling)
  1367. carla_stdout("CarlaEngine::callback [while idling] (%s, %s, %i:%s, %i, %i, %i, %i, %f, \"%s\")",
  1368. bool2str(sendHost), bool2str(sendOSC),
  1369. action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3,
  1370. static_cast<double>(valuef), valueStr);
  1371. else if (action != ENGINE_CALLBACK_IDLE && action != ENGINE_CALLBACK_NOTE_ON && action != ENGINE_CALLBACK_NOTE_OFF)
  1372. carla_debug("CarlaEngine::callback(%s, %s, %i:%s, %i, %i, %i, %i, %f, \"%s\")",
  1373. bool2str(sendHost), bool2str(sendOSC),
  1374. action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3,
  1375. static_cast<double>(valuef), valueStr);
  1376. #endif
  1377. if (sendHost && pData->callback != nullptr)
  1378. {
  1379. if (action == ENGINE_CALLBACK_IDLE)
  1380. ++pData->isIdling;
  1381. try {
  1382. pData->callback(pData->callbackPtr, action, pluginId, value1, value2, value3, valuef, valueStr);
  1383. } CARLA_SAFE_EXCEPTION("callback")
  1384. if (action == ENGINE_CALLBACK_IDLE)
  1385. --pData->isIdling;
  1386. }
  1387. if (sendOSC)
  1388. {
  1389. #if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE)
  1390. if (pData->osc.isControlRegisteredForTCP())
  1391. {
  1392. switch (action)
  1393. {
  1394. case ENGINE_CALLBACK_RELOAD_INFO:
  1395. {
  1396. CarlaPluginPtr plugin = pData->plugins[pluginId].plugin;
  1397. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  1398. pData->osc.sendPluginInfo(plugin);
  1399. break;
  1400. }
  1401. case ENGINE_CALLBACK_RELOAD_PARAMETERS:
  1402. {
  1403. CarlaPluginPtr plugin = pData->plugins[pluginId].plugin;
  1404. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  1405. pData->osc.sendPluginPortCount(plugin);
  1406. if (const uint32_t count = plugin->getParameterCount())
  1407. {
  1408. for (uint32_t i=0; i<count; ++i)
  1409. pData->osc.sendPluginParameterInfo(plugin, i);
  1410. }
  1411. break;
  1412. }
  1413. case ENGINE_CALLBACK_RELOAD_PROGRAMS:
  1414. {
  1415. CarlaPluginPtr plugin = pData->plugins[pluginId].plugin;
  1416. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  1417. pData->osc.sendPluginProgramCount(plugin);
  1418. if (const uint32_t count = plugin->getProgramCount())
  1419. {
  1420. for (uint32_t i=0; i<count; ++i)
  1421. pData->osc.sendPluginProgram(plugin, i);
  1422. }
  1423. if (const uint32_t count = plugin->getMidiProgramCount())
  1424. {
  1425. for (uint32_t i=0; i<count; ++i)
  1426. pData->osc.sendPluginMidiProgram(plugin, i);
  1427. }
  1428. break;
  1429. }
  1430. case ENGINE_CALLBACK_PLUGIN_ADDED:
  1431. case ENGINE_CALLBACK_RELOAD_ALL:
  1432. {
  1433. CarlaPluginPtr plugin = pData->plugins[pluginId].plugin;
  1434. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  1435. pData->osc.sendPluginInfo(plugin);
  1436. pData->osc.sendPluginPortCount(plugin);
  1437. pData->osc.sendPluginDataCount(plugin);
  1438. if (const uint32_t count = plugin->getParameterCount())
  1439. {
  1440. for (uint32_t i=0; i<count; ++i)
  1441. pData->osc.sendPluginParameterInfo(plugin, i);
  1442. }
  1443. if (const uint32_t count = plugin->getProgramCount())
  1444. {
  1445. for (uint32_t i=0; i<count; ++i)
  1446. pData->osc.sendPluginProgram(plugin, i);
  1447. }
  1448. if (const uint32_t count = plugin->getMidiProgramCount())
  1449. {
  1450. for (uint32_t i=0; i<count; ++i)
  1451. pData->osc.sendPluginMidiProgram(plugin, i);
  1452. }
  1453. if (const uint32_t count = plugin->getCustomDataCount())
  1454. {
  1455. for (uint32_t i=0; i<count; ++i)
  1456. pData->osc.sendPluginCustomData(plugin, i);
  1457. }
  1458. pData->osc.sendPluginInternalParameterValues(plugin);
  1459. break;
  1460. }
  1461. case ENGINE_CALLBACK_IDLE:
  1462. return;
  1463. default:
  1464. break;
  1465. }
  1466. pData->osc.sendCallback(action, pluginId, value1, value2, value3, valuef, valueStr);
  1467. }
  1468. #endif
  1469. }
  1470. }
  1471. void CarlaEngine::setCallback(const EngineCallbackFunc func, void* const ptr) noexcept
  1472. {
  1473. carla_debug("CarlaEngine::setCallback(%p, %p)", func, ptr);
  1474. pData->callback = func;
  1475. pData->callbackPtr = ptr;
  1476. }
  1477. // -----------------------------------------------------------------------
  1478. // File Callback
  1479. const char* CarlaEngine::runFileCallback(const FileCallbackOpcode action, const bool isDir, const char* const title, const char* const filter) noexcept
  1480. {
  1481. CARLA_SAFE_ASSERT_RETURN(title != nullptr && title[0] != '\0', nullptr);
  1482. CARLA_SAFE_ASSERT_RETURN(filter != nullptr, nullptr);
  1483. carla_debug("CarlaEngine::runFileCallback(%i:%s, %s, \"%s\", \"%s\")", action, FileCallbackOpcode2Str(action), bool2str(isDir), title, filter);
  1484. const char* ret = nullptr;
  1485. if (pData->fileCallback != nullptr)
  1486. {
  1487. try {
  1488. ret = pData->fileCallback(pData->fileCallbackPtr, action, isDir, title, filter);
  1489. } CARLA_SAFE_EXCEPTION("runFileCallback");
  1490. }
  1491. return ret;
  1492. }
  1493. void CarlaEngine::setFileCallback(const FileCallbackFunc func, void* const ptr) noexcept
  1494. {
  1495. carla_debug("CarlaEngine::setFileCallback(%p, %p)", func, ptr);
  1496. pData->fileCallback = func;
  1497. pData->fileCallbackPtr = ptr;
  1498. }
  1499. // -----------------------------------------------------------------------
  1500. // Transport
  1501. void CarlaEngine::transportPlay() noexcept
  1502. {
  1503. pData->timeInfo.playing = true;
  1504. pData->time.setNeedsReset();
  1505. }
  1506. void CarlaEngine::transportPause() noexcept
  1507. {
  1508. if (pData->timeInfo.playing)
  1509. pData->time.pause();
  1510. else
  1511. pData->time.setNeedsReset();
  1512. }
  1513. void CarlaEngine::transportBPM(const double bpm) noexcept
  1514. {
  1515. CARLA_SAFE_ASSERT_RETURN(bpm >= 20.0,)
  1516. try {
  1517. pData->time.setBPM(bpm);
  1518. } CARLA_SAFE_EXCEPTION("CarlaEngine::transportBPM");
  1519. }
  1520. void CarlaEngine::transportRelocate(const uint64_t frame) noexcept
  1521. {
  1522. pData->time.relocate(frame);
  1523. }
  1524. // -----------------------------------------------------------------------
  1525. // Error handling
  1526. const char* CarlaEngine::getLastError() const noexcept
  1527. {
  1528. return pData->lastError;
  1529. }
  1530. void CarlaEngine::setLastError(const char* const error) const noexcept
  1531. {
  1532. pData->lastError = error;
  1533. }
  1534. // -----------------------------------------------------------------------
  1535. // Misc
  1536. bool CarlaEngine::isAboutToClose() const noexcept
  1537. {
  1538. return pData->aboutToClose;
  1539. }
  1540. bool CarlaEngine::setAboutToClose() noexcept
  1541. {
  1542. carla_debug("CarlaEngine::setAboutToClose()");
  1543. pData->aboutToClose = true;
  1544. return (pData->isIdling == 0);
  1545. }
  1546. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1547. bool CarlaEngine::isLoadingProject() const noexcept
  1548. {
  1549. return pData->loadingProject;
  1550. }
  1551. #endif
  1552. void CarlaEngine::setActionCanceled(const bool canceled) noexcept
  1553. {
  1554. pData->actionCanceled = canceled;
  1555. }
  1556. bool CarlaEngine::wasActionCanceled() const noexcept
  1557. {
  1558. return pData->actionCanceled;
  1559. }
  1560. // -----------------------------------------------------------------------
  1561. // Global options
  1562. void CarlaEngine::setOption(const EngineOption option, const int value, const char* const valueStr) noexcept
  1563. {
  1564. carla_debug("CarlaEngine::setOption(%i:%s, %i, \"%s\")", option, EngineOption2Str(option), value, valueStr);
  1565. if (isRunning())
  1566. {
  1567. switch (option)
  1568. {
  1569. case ENGINE_OPTION_PROCESS_MODE:
  1570. case ENGINE_OPTION_AUDIO_TRIPLE_BUFFER:
  1571. case ENGINE_OPTION_AUDIO_DRIVER:
  1572. case ENGINE_OPTION_AUDIO_DEVICE:
  1573. return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Cannot set this option while engine is running!",
  1574. option, EngineOption2Str(option), value, valueStr);
  1575. default:
  1576. break;
  1577. }
  1578. }
  1579. // do not un-force stereo for rack mode
  1580. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && option == ENGINE_OPTION_FORCE_STEREO && value != 0)
  1581. return;
  1582. switch (option)
  1583. {
  1584. case ENGINE_OPTION_DEBUG:
  1585. break;
  1586. case ENGINE_OPTION_PROCESS_MODE:
  1587. CARLA_SAFE_ASSERT_RETURN(value >= ENGINE_PROCESS_MODE_SINGLE_CLIENT && value <= ENGINE_PROCESS_MODE_BRIDGE,);
  1588. pData->options.processMode = static_cast<EngineProcessMode>(value);
  1589. break;
  1590. case ENGINE_OPTION_TRANSPORT_MODE:
  1591. CARLA_SAFE_ASSERT_RETURN(value >= ENGINE_TRANSPORT_MODE_DISABLED && value <= ENGINE_TRANSPORT_MODE_BRIDGE,);
  1592. CARLA_SAFE_ASSERT_RETURN(getType() == kEngineTypeJack || value != ENGINE_TRANSPORT_MODE_JACK,);
  1593. pData->options.transportMode = static_cast<EngineTransportMode>(value);
  1594. delete[] pData->options.transportExtra;
  1595. if (value >= ENGINE_TRANSPORT_MODE_DISABLED && valueStr != nullptr)
  1596. pData->options.transportExtra = carla_strdup_safe(valueStr);
  1597. else
  1598. pData->options.transportExtra = nullptr;
  1599. pData->time.setNeedsReset();
  1600. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  1601. // enable link now if needed
  1602. {
  1603. const bool linkEnabled = pData->options.transportExtra != nullptr && std::strstr(pData->options.transportExtra, ":link:") != nullptr;
  1604. pData->time.enableLink(linkEnabled);
  1605. }
  1606. #endif
  1607. break;
  1608. case ENGINE_OPTION_FORCE_STEREO:
  1609. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1610. pData->options.forceStereo = (value != 0);
  1611. break;
  1612. case ENGINE_OPTION_PREFER_PLUGIN_BRIDGES:
  1613. #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1614. CARLA_SAFE_ASSERT_RETURN(value == 0,);
  1615. #else
  1616. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1617. #endif
  1618. pData->options.preferPluginBridges = (value != 0);
  1619. break;
  1620. case ENGINE_OPTION_PREFER_UI_BRIDGES:
  1621. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1622. pData->options.preferUiBridges = (value != 0);
  1623. break;
  1624. case ENGINE_OPTION_UIS_ALWAYS_ON_TOP:
  1625. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1626. pData->options.uisAlwaysOnTop = (value != 0);
  1627. break;
  1628. case ENGINE_OPTION_MAX_PARAMETERS:
  1629. CARLA_SAFE_ASSERT_RETURN(value >= 0,);
  1630. pData->options.maxParameters = static_cast<uint>(value);
  1631. break;
  1632. case ENGINE_OPTION_RESET_XRUNS:
  1633. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1634. pData->options.resetXruns = (value != 0);
  1635. break;
  1636. case ENGINE_OPTION_UI_BRIDGES_TIMEOUT:
  1637. CARLA_SAFE_ASSERT_RETURN(value >= 0,);
  1638. pData->options.uiBridgesTimeout = static_cast<uint>(value);
  1639. break;
  1640. case ENGINE_OPTION_AUDIO_BUFFER_SIZE:
  1641. CARLA_SAFE_ASSERT_RETURN(value >= 8,);
  1642. pData->options.audioBufferSize = static_cast<uint>(value);
  1643. break;
  1644. case ENGINE_OPTION_AUDIO_SAMPLE_RATE:
  1645. CARLA_SAFE_ASSERT_RETURN(value >= 22050,);
  1646. pData->options.audioSampleRate = static_cast<uint>(value);
  1647. break;
  1648. case ENGINE_OPTION_AUDIO_TRIPLE_BUFFER:
  1649. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1650. pData->options.audioTripleBuffer = (value != 0);
  1651. break;
  1652. case ENGINE_OPTION_AUDIO_DRIVER:
  1653. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,);
  1654. if (pData->options.audioDriver != nullptr)
  1655. delete[] pData->options.audioDriver;
  1656. pData->options.audioDriver = carla_strdup_safe(valueStr);
  1657. break;
  1658. case ENGINE_OPTION_AUDIO_DEVICE:
  1659. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,);
  1660. if (pData->options.audioDevice != nullptr)
  1661. delete[] pData->options.audioDevice;
  1662. pData->options.audioDevice = carla_strdup_safe(valueStr);
  1663. break;
  1664. #ifndef BUILD_BRIDGE
  1665. case ENGINE_OPTION_OSC_ENABLED:
  1666. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1667. pData->options.oscEnabled = (value != 0);
  1668. break;
  1669. case ENGINE_OPTION_OSC_PORT_TCP:
  1670. CARLA_SAFE_ASSERT_RETURN(value <= 0 || value >= 1024,);
  1671. pData->options.oscPortTCP = value;
  1672. break;
  1673. case ENGINE_OPTION_OSC_PORT_UDP:
  1674. CARLA_SAFE_ASSERT_RETURN(value <= 0 || value >= 1024,);
  1675. pData->options.oscPortUDP = value;
  1676. break;
  1677. #endif
  1678. case ENGINE_OPTION_FILE_PATH:
  1679. CARLA_SAFE_ASSERT_RETURN(value > FILE_NONE,);
  1680. CARLA_SAFE_ASSERT_RETURN(value <= FILE_MIDI,);
  1681. switch (value)
  1682. {
  1683. case FILE_AUDIO:
  1684. if (pData->options.pathAudio != nullptr)
  1685. delete[] pData->options.pathAudio;
  1686. if (valueStr != nullptr)
  1687. pData->options.pathAudio = carla_strdup_safe(valueStr);
  1688. else
  1689. pData->options.pathAudio = nullptr;
  1690. break;
  1691. case FILE_MIDI:
  1692. if (pData->options.pathMIDI != nullptr)
  1693. delete[] pData->options.pathMIDI;
  1694. if (valueStr != nullptr)
  1695. pData->options.pathMIDI = carla_strdup_safe(valueStr);
  1696. else
  1697. pData->options.pathMIDI = nullptr;
  1698. break;
  1699. default:
  1700. return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Invalid file type",
  1701. option, EngineOption2Str(option), value, valueStr);
  1702. break;
  1703. }
  1704. break;
  1705. case ENGINE_OPTION_PLUGIN_PATH:
  1706. CARLA_SAFE_ASSERT_RETURN(value > PLUGIN_NONE,);
  1707. CARLA_SAFE_ASSERT_RETURN(value <= PLUGIN_TYPE_COUNT,);
  1708. switch (value)
  1709. {
  1710. case PLUGIN_LADSPA:
  1711. if (pData->options.pathLADSPA != nullptr)
  1712. delete[] pData->options.pathLADSPA;
  1713. if (valueStr != nullptr)
  1714. pData->options.pathLADSPA = carla_strdup_safe(valueStr);
  1715. else
  1716. pData->options.pathLADSPA = nullptr;
  1717. break;
  1718. case PLUGIN_DSSI:
  1719. if (pData->options.pathDSSI != nullptr)
  1720. delete[] pData->options.pathDSSI;
  1721. if (valueStr != nullptr)
  1722. pData->options.pathDSSI = carla_strdup_safe(valueStr);
  1723. else
  1724. pData->options.pathDSSI = nullptr;
  1725. break;
  1726. case PLUGIN_LV2:
  1727. if (pData->options.pathLV2 != nullptr)
  1728. delete[] pData->options.pathLV2;
  1729. if (valueStr != nullptr)
  1730. pData->options.pathLV2 = carla_strdup_safe(valueStr);
  1731. else
  1732. pData->options.pathLV2 = nullptr;
  1733. break;
  1734. case PLUGIN_VST2:
  1735. if (pData->options.pathVST2 != nullptr)
  1736. delete[] pData->options.pathVST2;
  1737. if (valueStr != nullptr)
  1738. pData->options.pathVST2 = carla_strdup_safe(valueStr);
  1739. else
  1740. pData->options.pathVST2 = nullptr;
  1741. break;
  1742. case PLUGIN_VST3:
  1743. if (pData->options.pathVST3 != nullptr)
  1744. delete[] pData->options.pathVST3;
  1745. if (valueStr != nullptr)
  1746. pData->options.pathVST3 = carla_strdup_safe(valueStr);
  1747. else
  1748. pData->options.pathVST3 = nullptr;
  1749. break;
  1750. case PLUGIN_SF2:
  1751. if (pData->options.pathSF2 != nullptr)
  1752. delete[] pData->options.pathSF2;
  1753. if (valueStr != nullptr)
  1754. pData->options.pathSF2 = carla_strdup_safe(valueStr);
  1755. else
  1756. pData->options.pathSF2 = nullptr;
  1757. break;
  1758. case PLUGIN_SFZ:
  1759. if (pData->options.pathSFZ != nullptr)
  1760. delete[] pData->options.pathSFZ;
  1761. if (valueStr != nullptr)
  1762. pData->options.pathSFZ = carla_strdup_safe(valueStr);
  1763. else
  1764. pData->options.pathSFZ = nullptr;
  1765. break;
  1766. case PLUGIN_JSFX:
  1767. if (pData->options.pathJSFX != nullptr)
  1768. delete[] pData->options.pathJSFX;
  1769. if (valueStr != nullptr)
  1770. pData->options.pathJSFX = carla_strdup_safe(valueStr);
  1771. else
  1772. pData->options.pathJSFX = nullptr;
  1773. break;
  1774. case PLUGIN_CLAP:
  1775. if (pData->options.pathCLAP != nullptr)
  1776. delete[] pData->options.pathCLAP;
  1777. if (valueStr != nullptr)
  1778. pData->options.pathCLAP = carla_strdup_safe(valueStr);
  1779. else
  1780. pData->options.pathCLAP = nullptr;
  1781. break;
  1782. default:
  1783. return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Invalid plugin type",
  1784. option, EngineOption2Str(option), value, valueStr);
  1785. break;
  1786. }
  1787. break;
  1788. case ENGINE_OPTION_PATH_BINARIES:
  1789. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1790. if (pData->options.binaryDir != nullptr)
  1791. delete[] pData->options.binaryDir;
  1792. pData->options.binaryDir = carla_strdup_safe(valueStr);
  1793. break;
  1794. case ENGINE_OPTION_PATH_RESOURCES:
  1795. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1796. if (pData->options.resourceDir != nullptr)
  1797. delete[] pData->options.resourceDir;
  1798. pData->options.resourceDir = carla_strdup_safe(valueStr);
  1799. break;
  1800. case ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR: {
  1801. CARLA_SAFE_ASSERT_RETURN(pData->options.binaryDir != nullptr && pData->options.binaryDir[0] != '\0',);
  1802. #ifdef CARLA_OS_LINUX
  1803. const ScopedEngineEnvironmentLocker _seel(this);
  1804. if (value != 0)
  1805. {
  1806. CarlaString interposerPath(CarlaString(pData->options.binaryDir) + "/libcarla_interposer-safe.so");
  1807. ::setenv("LD_PRELOAD", interposerPath.buffer(), 1);
  1808. }
  1809. else
  1810. {
  1811. ::unsetenv("LD_PRELOAD");
  1812. }
  1813. #endif
  1814. } break;
  1815. case ENGINE_OPTION_FRONTEND_BACKGROUND_COLOR:
  1816. pData->options.bgColor = static_cast<uint>(value);
  1817. break;
  1818. case ENGINE_OPTION_FRONTEND_FOREGROUND_COLOR:
  1819. pData->options.fgColor = static_cast<uint>(value);
  1820. break;
  1821. case ENGINE_OPTION_FRONTEND_UI_SCALE:
  1822. CARLA_SAFE_ASSERT_RETURN(value > 0,);
  1823. pData->options.uiScale = static_cast<float>(value) / 1000;
  1824. break;
  1825. case ENGINE_OPTION_FRONTEND_WIN_ID: {
  1826. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1827. const long long winId(std::strtoll(valueStr, nullptr, 16));
  1828. CARLA_SAFE_ASSERT_RETURN(winId >= 0,);
  1829. pData->options.frontendWinId = static_cast<uintptr_t>(winId);
  1830. } break;
  1831. #if !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) && !defined(CARLA_OS_WIN)
  1832. case ENGINE_OPTION_WINE_EXECUTABLE:
  1833. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1834. if (pData->options.wine.executable != nullptr)
  1835. delete[] pData->options.wine.executable;
  1836. pData->options.wine.executable = carla_strdup_safe(valueStr);
  1837. break;
  1838. case ENGINE_OPTION_WINE_AUTO_PREFIX:
  1839. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1840. pData->options.wine.autoPrefix = (value != 0);
  1841. break;
  1842. case ENGINE_OPTION_WINE_FALLBACK_PREFIX:
  1843. CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
  1844. if (pData->options.wine.fallbackPrefix != nullptr)
  1845. delete[] pData->options.wine.fallbackPrefix;
  1846. pData->options.wine.fallbackPrefix = carla_strdup_safe(valueStr);
  1847. break;
  1848. case ENGINE_OPTION_WINE_RT_PRIO_ENABLED:
  1849. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1850. pData->options.wine.rtPrio = (value != 0);
  1851. break;
  1852. case ENGINE_OPTION_WINE_BASE_RT_PRIO:
  1853. CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 89,);
  1854. pData->options.wine.baseRtPrio = value;
  1855. break;
  1856. case ENGINE_OPTION_WINE_SERVER_RT_PRIO:
  1857. CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 99,);
  1858. pData->options.wine.serverRtPrio = value;
  1859. break;
  1860. #endif
  1861. #ifndef BUILD_BRIDGE
  1862. case ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT:
  1863. break;
  1864. #endif
  1865. case ENGINE_OPTION_CLIENT_NAME_PREFIX:
  1866. if (pData->options.clientNamePrefix != nullptr)
  1867. delete[] pData->options.clientNamePrefix;
  1868. pData->options.clientNamePrefix = valueStr != nullptr && valueStr[0] != '\0'
  1869. ? carla_strdup_safe(valueStr)
  1870. : nullptr;
  1871. break;
  1872. case ENGINE_OPTION_PLUGINS_ARE_STANDALONE:
  1873. CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
  1874. pData->options.pluginsAreStandalone = (value != 0);
  1875. break;
  1876. }
  1877. }
  1878. #ifndef BUILD_BRIDGE
  1879. // -----------------------------------------------------------------------
  1880. // OSC Stuff
  1881. bool CarlaEngine::isOscControlRegistered() const noexcept
  1882. {
  1883. # ifdef HAVE_LIBLO
  1884. return pData->osc.isControlRegisteredForTCP();
  1885. # else
  1886. return false;
  1887. # endif
  1888. }
  1889. const char* CarlaEngine::getOscServerPathTCP() const noexcept
  1890. {
  1891. # ifdef HAVE_LIBLO
  1892. return pData->osc.getServerPathTCP();
  1893. # else
  1894. return nullptr;
  1895. # endif
  1896. }
  1897. const char* CarlaEngine::getOscServerPathUDP() const noexcept
  1898. {
  1899. # ifdef HAVE_LIBLO
  1900. return pData->osc.getServerPathUDP();
  1901. # else
  1902. return nullptr;
  1903. # endif
  1904. }
  1905. #endif
  1906. // -----------------------------------------------------------------------
  1907. // Internal stuff
  1908. void CarlaEngine::bufferSizeChanged(const uint32_t newBufferSize)
  1909. {
  1910. carla_debug("CarlaEngine::bufferSizeChanged(%i)", newBufferSize);
  1911. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1912. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK ||
  1913. pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  1914. {
  1915. pData->graph.setBufferSize(newBufferSize);
  1916. }
  1917. #endif
  1918. pData->time.updateAudioValues(newBufferSize, pData->sampleRate);
  1919. for (uint i=0; i < pData->curPluginCount; ++i)
  1920. {
  1921. if (const CarlaPluginPtr plugin = pData->plugins[i].plugin)
  1922. {
  1923. if (plugin->isEnabled() && plugin->tryLock(true))
  1924. {
  1925. plugin->bufferSizeChanged(newBufferSize);
  1926. plugin->unlock();
  1927. }
  1928. }
  1929. }
  1930. callback(true, true, ENGINE_CALLBACK_BUFFER_SIZE_CHANGED, 0, static_cast<int>(newBufferSize), 0, 0, 0.0f, nullptr);
  1931. }
  1932. void CarlaEngine::sampleRateChanged(const double newSampleRate)
  1933. {
  1934. carla_debug("CarlaEngine::sampleRateChanged(%g)", newSampleRate);
  1935. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1936. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK ||
  1937. pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  1938. {
  1939. pData->graph.setSampleRate(newSampleRate);
  1940. }
  1941. #endif
  1942. pData->time.updateAudioValues(pData->bufferSize, newSampleRate);
  1943. for (uint i=0; i < pData->curPluginCount; ++i)
  1944. {
  1945. if (const CarlaPluginPtr plugin = pData->plugins[i].plugin)
  1946. {
  1947. if (plugin->isEnabled() && plugin->tryLock(true))
  1948. {
  1949. plugin->sampleRateChanged(newSampleRate);
  1950. plugin->unlock();
  1951. }
  1952. }
  1953. }
  1954. callback(true, true, ENGINE_CALLBACK_SAMPLE_RATE_CHANGED, 0, 0, 0, 0, static_cast<float>(newSampleRate), nullptr);
  1955. }
  1956. void CarlaEngine::offlineModeChanged(const bool isOfflineNow)
  1957. {
  1958. carla_debug("CarlaEngine::offlineModeChanged(%s)", bool2str(isOfflineNow));
  1959. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1960. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK ||
  1961. pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  1962. {
  1963. pData->graph.setOffline(isOfflineNow);
  1964. }
  1965. #endif
  1966. for (uint i=0; i < pData->curPluginCount; ++i)
  1967. {
  1968. if (const CarlaPluginPtr plugin = pData->plugins[i].plugin)
  1969. if (plugin->isEnabled())
  1970. plugin->offlineModeChanged(isOfflineNow);
  1971. }
  1972. }
  1973. void CarlaEngine::setPluginPeaksRT(const uint pluginId, float const inPeaks[2], float const outPeaks[2]) noexcept
  1974. {
  1975. EnginePluginData& pluginData(pData->plugins[pluginId]);
  1976. pluginData.peaks[0] = inPeaks[0];
  1977. pluginData.peaks[1] = inPeaks[1];
  1978. pluginData.peaks[2] = outPeaks[0];
  1979. pluginData.peaks[3] = outPeaks[1];
  1980. }
  1981. void CarlaEngine::saveProjectInternal(water::MemoryOutputStream& outStream) const
  1982. {
  1983. // send initial prepareForSave first, giving time for bridges to act
  1984. for (uint i=0; i < pData->curPluginCount; ++i)
  1985. {
  1986. if (const CarlaPluginPtr plugin = pData->plugins[i].plugin)
  1987. {
  1988. if (plugin->isEnabled())
  1989. {
  1990. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1991. // deactivate bridge client-side ping check, since some plugins block during save
  1992. if (plugin->getHints() & PLUGIN_IS_BRIDGE)
  1993. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "false", false);
  1994. #endif
  1995. plugin->prepareForSave(false);
  1996. }
  1997. }
  1998. }
  1999. outStream << "<?xml version='1.0' encoding='UTF-8'?>\n";
  2000. outStream << "<!DOCTYPE CARLA-PROJECT>\n";
  2001. outStream << "<CARLA-PROJECT VERSION='" CARLA_VERSION_STRMIN "'";
  2002. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2003. if (pData->ignoreClientPrefix)
  2004. outStream << " IgnoreClientPrefix='true'";
  2005. #endif
  2006. outStream << ">\n";
  2007. const bool isPlugin(getType() == kEngineTypePlugin);
  2008. const EngineOptions& options(pData->options);
  2009. {
  2010. MemoryOutputStream outSettings(1024);
  2011. outSettings << " <EngineSettings>\n";
  2012. outSettings << " <ForceStereo>" << bool2str(options.forceStereo) << "</ForceStereo>\n";
  2013. outSettings << " <PreferPluginBridges>" << bool2str(options.preferPluginBridges) << "</PreferPluginBridges>\n";
  2014. outSettings << " <PreferUiBridges>" << bool2str(options.preferUiBridges) << "</PreferUiBridges>\n";
  2015. outSettings << " <UIsAlwaysOnTop>" << bool2str(options.uisAlwaysOnTop) << "</UIsAlwaysOnTop>\n";
  2016. outSettings << " <MaxParameters>" << String(options.maxParameters) << "</MaxParameters>\n";
  2017. outSettings << " <UIBridgesTimeout>" << String(options.uiBridgesTimeout) << "</UIBridgesTimeout>\n";
  2018. if (isPlugin)
  2019. {
  2020. outSettings << " <LADSPA_PATH>" << xmlSafeString(options.pathLADSPA, true) << "</LADSPA_PATH>\n";
  2021. outSettings << " <DSSI_PATH>" << xmlSafeString(options.pathDSSI, true) << "</DSSI_PATH>\n";
  2022. outSettings << " <LV2_PATH>" << xmlSafeString(options.pathLV2, true) << "</LV2_PATH>\n";
  2023. outSettings << " <VST2_PATH>" << xmlSafeString(options.pathVST2, true) << "</VST2_PATH>\n";
  2024. outSettings << " <VST3_PATH>" << xmlSafeString(options.pathVST3, true) << "</VST3_PATH>\n";
  2025. outSettings << " <SF2_PATH>" << xmlSafeString(options.pathSF2, true) << "</SF2_PATH>\n";
  2026. outSettings << " <SFZ_PATH>" << xmlSafeString(options.pathSFZ, true) << "</SFZ_PATH>\n";
  2027. outSettings << " <JSFX_PATH>" << xmlSafeString(options.pathJSFX, true) << "</JSFX_PATH>\n";
  2028. outSettings << " <CLAP_PATH>" << xmlSafeString(options.pathCLAP, true) << "</CLAP_PATH>\n";
  2029. }
  2030. outSettings << " </EngineSettings>\n";
  2031. outStream << outSettings;
  2032. }
  2033. if (pData->timeInfo.bbt.valid && ! isPlugin)
  2034. {
  2035. MemoryOutputStream outTransport(128);
  2036. outTransport << "\n <Transport>\n";
  2037. // outTransport << " <BeatsPerBar>" << pData->timeInfo.bbt.beatsPerBar << "</BeatsPerBar>\n";
  2038. outTransport << " <BeatsPerMinute>" << pData->timeInfo.bbt.beatsPerMinute << "</BeatsPerMinute>\n";
  2039. outTransport << " </Transport>\n";
  2040. outStream << outTransport;
  2041. }
  2042. char strBuf[STR_MAX+1];
  2043. carla_zeroChars(strBuf, STR_MAX+1);
  2044. for (uint i=0; i < pData->curPluginCount; ++i)
  2045. {
  2046. if (const CarlaPluginPtr plugin = pData->plugins[i].plugin)
  2047. {
  2048. if (plugin->isEnabled())
  2049. {
  2050. MemoryOutputStream outPlugin(4096), streamPlugin;
  2051. plugin->getStateSave(false).dumpToMemoryStream(streamPlugin);
  2052. outPlugin << "\n";
  2053. if (plugin->getRealName(strBuf))
  2054. outPlugin << " <!-- " << xmlSafeString(strBuf, true) << " -->\n";
  2055. outPlugin << " <Plugin>\n";
  2056. outPlugin << streamPlugin;
  2057. outPlugin << " </Plugin>\n";
  2058. outStream << outPlugin;
  2059. }
  2060. }
  2061. }
  2062. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2063. // tell bridges we're done saving
  2064. for (uint i=0; i < pData->curPluginCount; ++i)
  2065. {
  2066. if (const CarlaPluginPtr plugin = pData->plugins[i].plugin)
  2067. if (plugin->isEnabled() && (plugin->getHints() & PLUGIN_IS_BRIDGE) != 0)
  2068. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "true", false);
  2069. }
  2070. // save internal connections
  2071. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  2072. {
  2073. uint posCount = 0;
  2074. const char* const* const patchbayConns = getPatchbayConnections(false);
  2075. const PatchbayPosition* const patchbayPos = getPatchbayPositions(false, posCount);
  2076. if (patchbayConns != nullptr || patchbayPos != nullptr)
  2077. {
  2078. MemoryOutputStream outPatchbay(2048);
  2079. outPatchbay << "\n <Patchbay>\n";
  2080. if (patchbayConns != nullptr)
  2081. {
  2082. for (int i=0; patchbayConns[i] != nullptr && patchbayConns[i+1] != nullptr; ++i, ++i)
  2083. {
  2084. const char* const connSource(patchbayConns[i]);
  2085. const char* const connTarget(patchbayConns[i+1]);
  2086. CARLA_SAFE_ASSERT_CONTINUE(connSource != nullptr && connSource[0] != '\0');
  2087. CARLA_SAFE_ASSERT_CONTINUE(connTarget != nullptr && connTarget[0] != '\0');
  2088. outPatchbay << " <Connection>\n";
  2089. outPatchbay << " <Source>" << xmlSafeString(connSource, true) << "</Source>\n";
  2090. outPatchbay << " <Target>" << xmlSafeString(connTarget, true) << "</Target>\n";
  2091. outPatchbay << " </Connection>\n";
  2092. }
  2093. }
  2094. if (patchbayPos != nullptr && posCount != 0)
  2095. {
  2096. outPatchbay << " <Positions>\n";
  2097. for (uint i=0; i<posCount; ++i)
  2098. {
  2099. const PatchbayPosition& ppos(patchbayPos[i]);
  2100. CARLA_SAFE_ASSERT_CONTINUE(ppos.name != nullptr && ppos.name[0] != '\0');
  2101. outPatchbay << " <Position x1=\"" << ppos.x1 << "\" y1=\"" << ppos.y1;
  2102. if (ppos.x2 != 0 || ppos.y2 != 0)
  2103. outPatchbay << "\" x2=\"" << ppos.x2 << "\" y2=\"" << ppos.y2;
  2104. if (ppos.pluginId >= 0)
  2105. outPatchbay << "\" pluginId=\"" << ppos.pluginId;
  2106. outPatchbay << "\">\n";
  2107. outPatchbay << " <Name>" << xmlSafeString(ppos.name, true) << "</Name>\n";
  2108. outPatchbay << " </Position>\n";
  2109. if (ppos.dealloc)
  2110. delete[] ppos.name;
  2111. }
  2112. outPatchbay << " </Positions>\n";
  2113. }
  2114. outPatchbay << " </Patchbay>\n";
  2115. outStream << outPatchbay;
  2116. delete[] patchbayPos;
  2117. }
  2118. }
  2119. // if we're running inside some session-manager (and using JACK), let them handle the connections
  2120. bool saveExternalConnections, saveExternalPositions = true;
  2121. /**/ if (isPlugin)
  2122. {
  2123. saveExternalConnections = false;
  2124. saveExternalPositions = false;
  2125. }
  2126. else if (std::strcmp(getCurrentDriverName(), "JACK") != 0)
  2127. {
  2128. saveExternalConnections = true;
  2129. }
  2130. else if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr)
  2131. {
  2132. saveExternalConnections = false;
  2133. }
  2134. else
  2135. {
  2136. saveExternalConnections = true;
  2137. }
  2138. if (saveExternalConnections || saveExternalPositions)
  2139. {
  2140. uint posCount = 0;
  2141. const char* const* const patchbayConns = saveExternalConnections
  2142. ? getPatchbayConnections(true)
  2143. : nullptr;
  2144. const PatchbayPosition* const patchbayPos = saveExternalPositions
  2145. ? getPatchbayPositions(true, posCount)
  2146. : nullptr;
  2147. if (patchbayConns != nullptr || patchbayPos != nullptr)
  2148. {
  2149. MemoryOutputStream outPatchbay(2048);
  2150. outPatchbay << "\n <ExternalPatchbay>\n";
  2151. if (patchbayConns != nullptr)
  2152. {
  2153. for (int i=0; patchbayConns[i] != nullptr && patchbayConns[i+1] != nullptr; ++i, ++i )
  2154. {
  2155. const char* const connSource(patchbayConns[i]);
  2156. const char* const connTarget(patchbayConns[i+1]);
  2157. CARLA_SAFE_ASSERT_CONTINUE(connSource != nullptr && connSource[0] != '\0');
  2158. CARLA_SAFE_ASSERT_CONTINUE(connTarget != nullptr && connTarget[0] != '\0');
  2159. outPatchbay << " <Connection>\n";
  2160. outPatchbay << " <Source>" << xmlSafeString(connSource, true) << "</Source>\n";
  2161. outPatchbay << " <Target>" << xmlSafeString(connTarget, true) << "</Target>\n";
  2162. outPatchbay << " </Connection>\n";
  2163. }
  2164. }
  2165. if (patchbayPos != nullptr && posCount != 0)
  2166. {
  2167. outPatchbay << " <Positions>\n";
  2168. for (uint i=0; i<posCount; ++i)
  2169. {
  2170. const PatchbayPosition& ppos(patchbayPos[i]);
  2171. CARLA_SAFE_ASSERT_CONTINUE(ppos.name != nullptr && ppos.name[0] != '\0');
  2172. outPatchbay << " <Position x1=\"" << ppos.x1 << "\" y1=\"" << ppos.y1;
  2173. if (ppos.x2 != 0 || ppos.y2 != 0)
  2174. outPatchbay << "\" x2=\"" << ppos.x2 << "\" y2=\"" << ppos.y2;
  2175. if (ppos.pluginId >= 0)
  2176. outPatchbay << "\" pluginId=\"" << ppos.pluginId;
  2177. outPatchbay << "\">\n";
  2178. outPatchbay << " <Name>" << xmlSafeString(ppos.name, true) << "</Name>\n";
  2179. outPatchbay << " </Position>\n";
  2180. if (ppos.dealloc)
  2181. delete[] ppos.name;
  2182. }
  2183. outPatchbay << " </Positions>\n";
  2184. }
  2185. outPatchbay << " </ExternalPatchbay>\n";
  2186. outStream << outPatchbay;
  2187. }
  2188. }
  2189. #endif
  2190. outStream << "</CARLA-PROJECT>\n";
  2191. }
  2192. static String findBinaryInCustomPath(const char* const searchPath, const char* const binary)
  2193. {
  2194. const StringArray searchPaths(StringArray::fromTokens(searchPath, CARLA_OS_SPLIT_STR, ""));
  2195. // try direct filename first
  2196. String jbinary(binary);
  2197. // adjust for current platform
  2198. #ifdef CARLA_OS_WIN
  2199. if (jbinary[0] == '/')
  2200. jbinary = "C:" + jbinary.replaceCharacter('/', '\\');
  2201. #else
  2202. if (jbinary[1] == ':' && (jbinary[2] == '\\' || jbinary[2] == '/'))
  2203. jbinary = jbinary.substring(2).replaceCharacter('\\', '/');
  2204. #endif
  2205. String filename = File(jbinary).getFileName();
  2206. int searchFlags = File::findFiles|File::ignoreHiddenFiles;
  2207. if (filename.endsWithIgnoreCase(".vst3"))
  2208. searchFlags |= File::findDirectories;
  2209. #ifdef CARLA_OS_MAC
  2210. else if (filename.endsWithIgnoreCase(".vst"))
  2211. searchFlags |= File::findDirectories;
  2212. #endif
  2213. std::vector<File> results;
  2214. for (const String *it=searchPaths.begin(), *end=searchPaths.end(); it != end; ++it)
  2215. {
  2216. const File path(*it);
  2217. results.clear();
  2218. path.findChildFiles(results, searchFlags, true, filename);
  2219. if (!results.empty())
  2220. return results.front().getFullPathName();
  2221. }
  2222. // try changing extension
  2223. #if defined(CARLA_OS_MAC)
  2224. if (filename.endsWithIgnoreCase(".dll") || filename.endsWithIgnoreCase(".so"))
  2225. filename = File(jbinary).getFileNameWithoutExtension() + ".dylib";
  2226. #elif defined(CARLA_OS_WIN)
  2227. if (filename.endsWithIgnoreCase(".dylib") || filename.endsWithIgnoreCase(".so"))
  2228. filename = File(jbinary).getFileNameWithoutExtension() + ".dll";
  2229. #else
  2230. if (filename.endsWithIgnoreCase(".dll") || filename.endsWithIgnoreCase(".dylib"))
  2231. filename = File(jbinary).getFileNameWithoutExtension() + ".so";
  2232. #endif
  2233. else
  2234. return String();
  2235. for (const String *it=searchPaths.begin(), *end=searchPaths.end(); it != end; ++it)
  2236. {
  2237. const File path(*it);
  2238. results.clear();
  2239. path.findChildFiles(results, searchFlags, true, filename);
  2240. if (!results.empty())
  2241. return results.front().getFullPathName();
  2242. }
  2243. return String();
  2244. }
  2245. bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alwaysLoadConnections)
  2246. {
  2247. carla_debug("CarlaEngine::loadProjectInternal(%p, %s) - START", &xmlDoc, bool2str(alwaysLoadConnections));
  2248. CarlaScopedPointer<XmlElement> xmlElement(xmlDoc.getDocumentElement(true));
  2249. CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to parse project file");
  2250. const String& xmlType(xmlElement->getTagName());
  2251. const bool isPreset(xmlType.equalsIgnoreCase("carla-preset"));
  2252. if (! (xmlType.equalsIgnoreCase("carla-project") || isPreset))
  2253. {
  2254. callback(true, true, ENGINE_CALLBACK_PROJECT_LOAD_FINISHED, 0, 0, 0, 0, 0.0f, nullptr);
  2255. setLastError("Not a valid Carla project or preset file");
  2256. return false;
  2257. }
  2258. pData->actionCanceled = false;
  2259. callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, 0, 1, 0, 0, 0.0f, "Loading project");
  2260. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2261. if (pData->options.clientNamePrefix != nullptr)
  2262. {
  2263. if (carla_isEqual(xmlElement->getDoubleAttribute("VERSION", 0.0), 2.0) ||
  2264. xmlElement->getBoolAttribute("IgnoreClientPrefix", false))
  2265. {
  2266. carla_stdout("Loading project in compatibility mode, will ignore client name prefix");
  2267. pData->ignoreClientPrefix = true;
  2268. setOption(ENGINE_OPTION_CLIENT_NAME_PREFIX, 0, "");
  2269. }
  2270. }
  2271. const CarlaScopedValueSetter<bool> csvs(pData->loadingProject, true, false);
  2272. #endif
  2273. // completely load file
  2274. xmlElement = xmlDoc.getDocumentElement(false);
  2275. CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to completely parse project file");
  2276. if (pData->aboutToClose)
  2277. return true;
  2278. if (pData->actionCanceled)
  2279. {
  2280. setLastError("Project load canceled");
  2281. return false;
  2282. }
  2283. callback(true, false, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2284. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2285. const bool isMultiClient = pData->options.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS;
  2286. const bool isPatchbay = pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY;
  2287. #endif
  2288. const bool isPlugin = getType() == kEngineTypePlugin;
  2289. // load engine settings first of all
  2290. if (XmlElement* const elem = isPreset ? nullptr : xmlElement->getChildByName("EngineSettings"))
  2291. {
  2292. for (XmlElement* settElem = elem->getFirstChildElement(); settElem != nullptr; settElem = settElem->getNextElement())
  2293. {
  2294. const String& tag(settElem->getTagName());
  2295. const String text(settElem->getAllSubText().trim());
  2296. /** some settings might be incorrect or require extra work,
  2297. so we call setOption rather than modifying them direly */
  2298. int option = -1;
  2299. int value = 0;
  2300. const char* valueStr = nullptr;
  2301. /**/ if (tag == "ForceStereo")
  2302. {
  2303. option = ENGINE_OPTION_FORCE_STEREO;
  2304. value = text == "true" ? 1 : 0;
  2305. }
  2306. else if (tag == "PreferPluginBridges")
  2307. {
  2308. option = ENGINE_OPTION_PREFER_PLUGIN_BRIDGES;
  2309. value = text == "true" ? 1 : 0;
  2310. }
  2311. else if (tag == "PreferUiBridges")
  2312. {
  2313. option = ENGINE_OPTION_PREFER_UI_BRIDGES;
  2314. value = text == "true" ? 1 : 0;
  2315. }
  2316. else if (tag == "UIsAlwaysOnTop")
  2317. {
  2318. option = ENGINE_OPTION_UIS_ALWAYS_ON_TOP;
  2319. value = text == "true" ? 1 : 0;
  2320. }
  2321. else if (tag == "MaxParameters")
  2322. {
  2323. option = ENGINE_OPTION_MAX_PARAMETERS;
  2324. value = text.getIntValue();
  2325. }
  2326. else if (tag == "UIBridgesTimeout")
  2327. {
  2328. option = ENGINE_OPTION_UI_BRIDGES_TIMEOUT;
  2329. value = text.getIntValue();
  2330. }
  2331. else if (isPlugin)
  2332. {
  2333. /**/ if (tag == "LADSPA_PATH")
  2334. {
  2335. option = ENGINE_OPTION_PLUGIN_PATH;
  2336. value = PLUGIN_LADSPA;
  2337. valueStr = text.toRawUTF8();
  2338. }
  2339. else if (tag == "DSSI_PATH")
  2340. {
  2341. option = ENGINE_OPTION_PLUGIN_PATH;
  2342. value = PLUGIN_DSSI;
  2343. valueStr = text.toRawUTF8();
  2344. }
  2345. else if (tag == "LV2_PATH")
  2346. {
  2347. option = ENGINE_OPTION_PLUGIN_PATH;
  2348. value = PLUGIN_LV2;
  2349. valueStr = text.toRawUTF8();
  2350. }
  2351. else if (tag == "VST2_PATH")
  2352. {
  2353. option = ENGINE_OPTION_PLUGIN_PATH;
  2354. value = PLUGIN_VST2;
  2355. valueStr = text.toRawUTF8();
  2356. }
  2357. else if (tag.equalsIgnoreCase("VST3_PATH"))
  2358. {
  2359. option = ENGINE_OPTION_PLUGIN_PATH;
  2360. value = PLUGIN_VST3;
  2361. valueStr = text.toRawUTF8();
  2362. }
  2363. else if (tag == "SF2_PATH")
  2364. {
  2365. option = ENGINE_OPTION_PLUGIN_PATH;
  2366. value = PLUGIN_SF2;
  2367. valueStr = text.toRawUTF8();
  2368. }
  2369. else if (tag == "SFZ_PATH")
  2370. {
  2371. option = ENGINE_OPTION_PLUGIN_PATH;
  2372. value = PLUGIN_SFZ;
  2373. valueStr = text.toRawUTF8();
  2374. }
  2375. else if (tag == "JSFX_PATH")
  2376. {
  2377. option = ENGINE_OPTION_PLUGIN_PATH;
  2378. value = PLUGIN_JSFX;
  2379. valueStr = text.toRawUTF8();
  2380. }
  2381. else if (tag == "CLAP_PATH")
  2382. {
  2383. option = ENGINE_OPTION_PLUGIN_PATH;
  2384. value = PLUGIN_CLAP;
  2385. valueStr = text.toRawUTF8();
  2386. }
  2387. }
  2388. if (option == -1)
  2389. {
  2390. // check old stuff, unhandled now
  2391. if (tag == "GIG_PATH")
  2392. continue;
  2393. // ignored tags
  2394. if (tag == "LADSPA_PATH" || tag == "DSSI_PATH" || tag == "LV2_PATH" || tag == "VST2_PATH")
  2395. continue;
  2396. if (tag == "VST3_PATH" || tag == "AU_PATH")
  2397. continue;
  2398. if (tag == "SF2_PATH" || tag == "SFZ_PATH" || tag == "JSFX_PATH" || tag == "CLAP_PATH")
  2399. continue;
  2400. // hmm something is wrong..
  2401. carla_stderr2("CarlaEngine::loadProjectInternal() - Unhandled option '%s'", tag.toRawUTF8());
  2402. continue;
  2403. }
  2404. setOption(static_cast<EngineOption>(option), value, valueStr);
  2405. }
  2406. if (pData->aboutToClose)
  2407. return true;
  2408. if (pData->actionCanceled)
  2409. {
  2410. setLastError("Project load canceled");
  2411. return false;
  2412. }
  2413. }
  2414. // now setup transport
  2415. if (XmlElement* const elem = (isPreset || isPlugin) ? nullptr : xmlElement->getChildByName("Transport"))
  2416. {
  2417. if (XmlElement* const bpmElem = elem->getChildByName("BeatsPerMinute"))
  2418. {
  2419. const String bpmText(bpmElem->getAllSubText().trim());
  2420. const double bpm = bpmText.getDoubleValue();
  2421. // some sane limits
  2422. if (bpm >= 20.0 && bpm < 400.0)
  2423. pData->time.setBPM(bpm);
  2424. if (pData->aboutToClose)
  2425. return true;
  2426. if (pData->actionCanceled)
  2427. {
  2428. setLastError("Project load canceled");
  2429. return false;
  2430. }
  2431. }
  2432. }
  2433. // and we handle plugins
  2434. for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
  2435. {
  2436. const String& tagName(elem->getTagName());
  2437. if (isPreset || tagName == "Plugin")
  2438. {
  2439. CarlaStateSave stateSave;
  2440. stateSave.fillFromXmlElement(isPreset ? xmlElement.get() : elem);
  2441. if (pData->aboutToClose)
  2442. return true;
  2443. if (pData->actionCanceled)
  2444. {
  2445. setLastError("Project load canceled");
  2446. return false;
  2447. }
  2448. CARLA_SAFE_ASSERT_CONTINUE(stateSave.type != nullptr);
  2449. #if !(defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) || defined(CARLA_PLUGIN_ONLY_BRIDGE))
  2450. // compatibility code to load projects with GIG files
  2451. // FIXME Remove on 2.1 release
  2452. if (std::strcmp(stateSave.type, "GIG") == 0)
  2453. {
  2454. if (addPlugin(PLUGIN_LV2, "", stateSave.name, "http://linuxsampler.org/plugins/linuxsampler", 0, nullptr))
  2455. {
  2456. const uint pluginId = pData->curPluginCount;
  2457. if (const CarlaPluginPtr plugin = pData->plugins[pluginId].plugin)
  2458. {
  2459. if (pData->aboutToClose)
  2460. return true;
  2461. if (pData->actionCanceled)
  2462. {
  2463. setLastError("Project load canceled");
  2464. return false;
  2465. }
  2466. String lsState;
  2467. lsState << "0.35\n";
  2468. lsState << "18 0 Chromatic\n";
  2469. lsState << "18 1 Drum Kits\n";
  2470. lsState << "20 0\n";
  2471. lsState << "0 1 " << stateSave.binary << "\n";
  2472. lsState << "0 0 0 0 1 0 GIG\n";
  2473. plugin->setCustomData(LV2_ATOM__String, "http://linuxsampler.org/schema#state-string", lsState.toRawUTF8(), true);
  2474. plugin->restoreLV2State(true);
  2475. plugin->setDryWet(stateSave.dryWet, true, true);
  2476. plugin->setVolume(stateSave.volume, true, true);
  2477. plugin->setBalanceLeft(stateSave.balanceLeft, true, true);
  2478. plugin->setBalanceRight(stateSave.balanceRight, true, true);
  2479. plugin->setPanning(stateSave.panning, true, true);
  2480. plugin->setCtrlChannel(stateSave.ctrlChannel, true, true);
  2481. plugin->setActive(stateSave.active, true, true);
  2482. plugin->setEnabled(true);
  2483. ++pData->curPluginCount;
  2484. callback(true, true, ENGINE_CALLBACK_PLUGIN_ADDED, pluginId, plugin->getType(),
  2485. 0, 0, 0.0f,
  2486. plugin->getName());
  2487. if (isPatchbay)
  2488. pData->graph.addPlugin(plugin);
  2489. }
  2490. else
  2491. {
  2492. carla_stderr2("Failed to get new plugin, state will not be restored correctly\n");
  2493. }
  2494. }
  2495. else
  2496. {
  2497. carla_stderr2("Failed to load a linuxsampler LV2 plugin, GIG file won't be loaded");
  2498. }
  2499. callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2500. continue;
  2501. }
  2502. #ifdef SFZ_FILES_USING_SFIZZ
  2503. if (std::strcmp(stateSave.type, "SFZ") == 0)
  2504. {
  2505. if (addPlugin(PLUGIN_LV2, "", stateSave.name, "http://sfztools.github.io/sfizz", 0, nullptr))
  2506. {
  2507. const uint pluginId = pData->curPluginCount;
  2508. if (const CarlaPluginPtr plugin = pData->plugins[pluginId].plugin)
  2509. {
  2510. if (pData->aboutToClose)
  2511. return true;
  2512. if (pData->actionCanceled)
  2513. {
  2514. setLastError("Project load canceled");
  2515. return false;
  2516. }
  2517. plugin->setCustomData(LV2_ATOM__Path,
  2518. "http://sfztools.github.io/sfizz:sfzfile",
  2519. stateSave.binary,
  2520. false);
  2521. plugin->restoreLV2State(true);
  2522. plugin->setDryWet(stateSave.dryWet, true, true);
  2523. plugin->setVolume(stateSave.volume, true, true);
  2524. plugin->setBalanceLeft(stateSave.balanceLeft, true, true);
  2525. plugin->setBalanceRight(stateSave.balanceRight, true, true);
  2526. plugin->setPanning(stateSave.panning, true, true);
  2527. plugin->setCtrlChannel(stateSave.ctrlChannel, true, true);
  2528. plugin->setActive(stateSave.active, true, true);
  2529. plugin->setEnabled(true);
  2530. ++pData->curPluginCount;
  2531. callback(true, true, ENGINE_CALLBACK_PLUGIN_ADDED, pluginId, plugin->getType(),
  2532. 0, 0, 0.0f,
  2533. plugin->getName());
  2534. if (isPatchbay)
  2535. pData->graph.addPlugin(plugin);
  2536. }
  2537. else
  2538. {
  2539. carla_stderr2("Failed to get new plugin, state will not be restored correctly\n");
  2540. }
  2541. }
  2542. else
  2543. {
  2544. carla_stderr2("Failed to load a sfizz LV2 plugin, SFZ file won't be loaded");
  2545. }
  2546. callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2547. continue;
  2548. }
  2549. #endif
  2550. #endif
  2551. const void* extraStuff = nullptr;
  2552. static const char kTrue[] = "true";
  2553. const PluginType ptype = getPluginTypeFromString(stateSave.type);
  2554. switch (ptype)
  2555. {
  2556. case PLUGIN_SF2:
  2557. if (CarlaString(stateSave.label).endsWith(" (16 outs)"))
  2558. extraStuff = kTrue;
  2559. // fall through
  2560. case PLUGIN_LADSPA:
  2561. case PLUGIN_DSSI:
  2562. case PLUGIN_VST2:
  2563. case PLUGIN_VST3:
  2564. case PLUGIN_SFZ:
  2565. case PLUGIN_JSFX:
  2566. case PLUGIN_CLAP:
  2567. if (stateSave.binary != nullptr && stateSave.binary[0] != '\0' &&
  2568. ! (File::isAbsolutePath(stateSave.binary) && File(stateSave.binary).exists()))
  2569. {
  2570. const char* searchPath;
  2571. switch (ptype)
  2572. {
  2573. case PLUGIN_LADSPA: searchPath = pData->options.pathLADSPA; break;
  2574. case PLUGIN_DSSI: searchPath = pData->options.pathDSSI; break;
  2575. case PLUGIN_VST2: searchPath = pData->options.pathVST2; break;
  2576. case PLUGIN_VST3: searchPath = pData->options.pathVST3; break;
  2577. case PLUGIN_SF2: searchPath = pData->options.pathSF2; break;
  2578. case PLUGIN_SFZ: searchPath = pData->options.pathSFZ; break;
  2579. case PLUGIN_JSFX: searchPath = pData->options.pathJSFX; break;
  2580. case PLUGIN_CLAP: searchPath = pData->options.pathCLAP; break;
  2581. default: searchPath = nullptr; break;
  2582. }
  2583. if (searchPath != nullptr && searchPath[0] != '\0')
  2584. {
  2585. carla_stderr("Plugin binary '%s' doesn't exist on this filesystem, let's look for it...",
  2586. stateSave.binary);
  2587. String result = findBinaryInCustomPath(searchPath, stateSave.binary);
  2588. if (result.isEmpty())
  2589. {
  2590. switch (ptype)
  2591. {
  2592. case PLUGIN_LADSPA: searchPath = std::getenv("LADSPA_PATH"); break;
  2593. case PLUGIN_DSSI: searchPath = std::getenv("DSSI_PATH"); break;
  2594. case PLUGIN_VST2: searchPath = std::getenv("VST_PATH"); break;
  2595. case PLUGIN_VST3: searchPath = std::getenv("VST3_PATH"); break;
  2596. case PLUGIN_SF2: searchPath = std::getenv("SF2_PATH"); break;
  2597. case PLUGIN_SFZ: searchPath = std::getenv("SFZ_PATH"); break;
  2598. case PLUGIN_JSFX: searchPath = std::getenv("JSFX_PATH"); break;
  2599. case PLUGIN_CLAP: searchPath = std::getenv("CLAP_PATH"); break;
  2600. default: searchPath = nullptr; break;
  2601. }
  2602. if (searchPath != nullptr && searchPath[0] != '\0')
  2603. result = findBinaryInCustomPath(searchPath, stateSave.binary);
  2604. }
  2605. if (result.isNotEmpty())
  2606. {
  2607. delete[] stateSave.binary;
  2608. stateSave.binary = carla_strdup(result.toRawUTF8());
  2609. carla_stderr("Found it! :)");
  2610. }
  2611. else
  2612. {
  2613. carla_stderr("Damn, we failed... :(");
  2614. }
  2615. callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2616. }
  2617. }
  2618. break;
  2619. default:
  2620. break;
  2621. }
  2622. BinaryType btype;
  2623. switch (ptype)
  2624. {
  2625. case PLUGIN_LADSPA:
  2626. case PLUGIN_DSSI:
  2627. case PLUGIN_LV2:
  2628. case PLUGIN_VST2:
  2629. case PLUGIN_VST3:
  2630. case PLUGIN_CLAP:
  2631. btype = getBinaryTypeFromFile(stateSave.binary);
  2632. break;
  2633. default:
  2634. btype = BINARY_NATIVE;
  2635. break;
  2636. }
  2637. if (addPlugin(btype, ptype, stateSave.binary,
  2638. stateSave.name, stateSave.label, stateSave.uniqueId, extraStuff, stateSave.options))
  2639. {
  2640. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2641. const uint pluginId = pData->curPluginCount;
  2642. #else
  2643. const uint pluginId = 0;
  2644. #endif
  2645. if (const CarlaPluginPtr plugin = pData->plugins[pluginId].plugin)
  2646. {
  2647. if (pData->aboutToClose)
  2648. return true;
  2649. if (pData->actionCanceled)
  2650. {
  2651. setLastError("Project load canceled");
  2652. return false;
  2653. }
  2654. // deactivate bridge client-side ping check, since some plugins block during load
  2655. if ((plugin->getHints() & PLUGIN_IS_BRIDGE) != 0 && ! isPreset)
  2656. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "false", false);
  2657. plugin->loadStateSave(stateSave);
  2658. /* NOTE: The following code is the same as the end of addPlugin().
  2659. * When project is loading we do not enable the plugin right away,
  2660. * as we want to load state first.
  2661. */
  2662. plugin->setEnabled(true);
  2663. ++pData->curPluginCount;
  2664. callback(true, true, ENGINE_CALLBACK_PLUGIN_ADDED, pluginId, plugin->getType(),
  2665. 0, 0, 0.0f,
  2666. plugin->getName());
  2667. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2668. if (isPatchbay)
  2669. pData->graph.addPlugin(plugin);
  2670. #endif
  2671. }
  2672. else
  2673. {
  2674. carla_stderr2("Failed to get new plugin, state will not be restored correctly\n");
  2675. }
  2676. }
  2677. else
  2678. {
  2679. carla_stderr2("Failed to load a plugin '%s', error was:\n%s", stateSave.name, getLastError());
  2680. }
  2681. if (! isPreset)
  2682. callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2683. }
  2684. if (isPreset)
  2685. {
  2686. callback(true, true, ENGINE_CALLBACK_PROJECT_LOAD_FINISHED, 0, 0, 0, 0, 0.0f, nullptr);
  2687. callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, 0, 0, 0, 0, 0.0f, "Loading project");
  2688. return true;
  2689. }
  2690. }
  2691. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2692. // tell bridges we're done loading
  2693. for (uint i=0; i < pData->curPluginCount; ++i)
  2694. {
  2695. if (const CarlaPluginPtr plugin = pData->plugins[i].plugin)
  2696. if (plugin->isEnabled() && (plugin->getHints() & PLUGIN_IS_BRIDGE) != 0)
  2697. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "true", false);
  2698. }
  2699. if (pData->aboutToClose)
  2700. return true;
  2701. if (pData->actionCanceled)
  2702. {
  2703. setLastError("Project load canceled");
  2704. return false;
  2705. }
  2706. // now we handle positions
  2707. bool loadingAsExternal;
  2708. std::map<water::String, water::String> mapGroupNamesInternal, mapGroupNamesExternal;
  2709. bool hasInternalPositions = false;
  2710. if (XmlElement* const elemPatchbay = xmlElement->getChildByName("Patchbay"))
  2711. {
  2712. hasInternalPositions = true;
  2713. if (XmlElement* const elemPositions = elemPatchbay->getChildByName("Positions"))
  2714. {
  2715. String name;
  2716. PatchbayPosition ppos = { nullptr, -1, 0, 0, 0, 0, false };
  2717. for (XmlElement* patchElem = elemPositions->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement())
  2718. {
  2719. const String& patchTag(patchElem->getTagName());
  2720. if (patchTag != "Position")
  2721. continue;
  2722. XmlElement* const patchName = patchElem->getChildByName("Name");
  2723. CARLA_SAFE_ASSERT_CONTINUE(patchName != nullptr);
  2724. const String nameText(patchName->getAllSubText().trim());
  2725. name = xmlSafeString(nameText, false);
  2726. ppos.name = name.toRawUTF8();
  2727. ppos.x1 = patchElem->getIntAttribute("x1");
  2728. ppos.y1 = patchElem->getIntAttribute("y1");
  2729. ppos.x2 = patchElem->getIntAttribute("x2");
  2730. ppos.y2 = patchElem->getIntAttribute("y2");
  2731. ppos.pluginId = patchElem->getIntAttribute("pluginId", -1);
  2732. ppos.dealloc = false;
  2733. loadingAsExternal = ppos.pluginId >= 0 && isMultiClient;
  2734. if (name.isNotEmpty() && restorePatchbayGroupPosition(loadingAsExternal, ppos))
  2735. {
  2736. if (name != ppos.name)
  2737. {
  2738. carla_stdout("Converted client name '%s' to '%s' for this session",
  2739. name.toRawUTF8(), ppos.name);
  2740. if (loadingAsExternal)
  2741. mapGroupNamesExternal[name] = ppos.name;
  2742. else
  2743. mapGroupNamesInternal[name] = ppos.name;
  2744. }
  2745. if (ppos.dealloc)
  2746. std::free(const_cast<char*>(ppos.name));
  2747. }
  2748. }
  2749. if (pData->aboutToClose)
  2750. return true;
  2751. if (pData->actionCanceled)
  2752. {
  2753. setLastError("Project load canceled");
  2754. return false;
  2755. }
  2756. }
  2757. }
  2758. if (XmlElement* const elemPatchbay = xmlElement->getChildByName("ExternalPatchbay"))
  2759. {
  2760. if (XmlElement* const elemPositions = elemPatchbay->getChildByName("Positions"))
  2761. {
  2762. String name;
  2763. PatchbayPosition ppos = { nullptr, -1, 0, 0, 0, 0, false };
  2764. for (XmlElement* patchElem = elemPositions->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement())
  2765. {
  2766. const String& patchTag(patchElem->getTagName());
  2767. if (patchTag != "Position")
  2768. continue;
  2769. XmlElement* const patchName = patchElem->getChildByName("Name");
  2770. CARLA_SAFE_ASSERT_CONTINUE(patchName != nullptr);
  2771. const String nameText(patchName->getAllSubText().trim());
  2772. name = xmlSafeString(nameText, false);
  2773. ppos.name = name.toRawUTF8();
  2774. ppos.x1 = patchElem->getIntAttribute("x1");
  2775. ppos.y1 = patchElem->getIntAttribute("y1");
  2776. ppos.x2 = patchElem->getIntAttribute("x2");
  2777. ppos.y2 = patchElem->getIntAttribute("y2");
  2778. ppos.pluginId = patchElem->getIntAttribute("pluginId", -1);
  2779. ppos.dealloc = false;
  2780. loadingAsExternal = ppos.pluginId < 0 || hasInternalPositions || !isPatchbay;
  2781. carla_debug("loadingAsExternal: %i because %i %i %i",
  2782. loadingAsExternal, ppos.pluginId < 0, hasInternalPositions, !isPatchbay);
  2783. if (name.isNotEmpty() && restorePatchbayGroupPosition(loadingAsExternal, ppos))
  2784. {
  2785. if (name != ppos.name)
  2786. {
  2787. carla_stdout("Converted client name '%s' to '%s' for this session",
  2788. name.toRawUTF8(), ppos.name);
  2789. if (loadingAsExternal)
  2790. mapGroupNamesExternal[name] = ppos.name;
  2791. else
  2792. mapGroupNamesInternal[name] = ppos.name;
  2793. }
  2794. if (ppos.dealloc)
  2795. std::free(const_cast<char*>(ppos.name));
  2796. }
  2797. }
  2798. if (pData->aboutToClose)
  2799. return true;
  2800. if (pData->actionCanceled)
  2801. {
  2802. setLastError("Project load canceled");
  2803. return false;
  2804. }
  2805. }
  2806. }
  2807. bool hasInternalConnections = false;
  2808. // and now we handle connections (internal)
  2809. if (XmlElement* const elem = xmlElement->getChildByName("Patchbay"))
  2810. {
  2811. hasInternalConnections = true;
  2812. if (isPatchbay)
  2813. {
  2814. water::String sourcePort, targetPort;
  2815. for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement())
  2816. {
  2817. const String& patchTag(patchElem->getTagName());
  2818. if (patchTag != "Connection")
  2819. continue;
  2820. sourcePort.clear();
  2821. targetPort.clear();
  2822. for (XmlElement* connElem = patchElem->getFirstChildElement(); connElem != nullptr; connElem = connElem->getNextElement())
  2823. {
  2824. const String& tag(connElem->getTagName());
  2825. const String text(connElem->getAllSubText().trim());
  2826. /**/ if (tag == "Source")
  2827. sourcePort = xmlSafeString(text, false);
  2828. else if (tag == "Target")
  2829. targetPort = xmlSafeString(text, false);
  2830. }
  2831. if (sourcePort.isNotEmpty() && targetPort.isNotEmpty())
  2832. {
  2833. std::map<water::String, water::String>& map(mapGroupNamesInternal);
  2834. std::map<water::String, water::String>::iterator it;
  2835. if ((it = map.find(sourcePort.upToFirstOccurrenceOf(":", false, false))) != map.end())
  2836. sourcePort = it->second + sourcePort.fromFirstOccurrenceOf(":", true, false);
  2837. if ((it = map.find(targetPort.upToFirstOccurrenceOf(":", false, false))) != map.end())
  2838. targetPort = it->second + targetPort.fromFirstOccurrenceOf(":", true, false);
  2839. restorePatchbayConnection(false, sourcePort.toRawUTF8(), targetPort.toRawUTF8());
  2840. }
  2841. }
  2842. if (pData->aboutToClose)
  2843. return true;
  2844. if (pData->actionCanceled)
  2845. {
  2846. setLastError("Project load canceled");
  2847. return false;
  2848. }
  2849. }
  2850. }
  2851. // if we're running inside some session-manager (and using JACK), let them handle the external connections
  2852. bool loadExternalConnections;
  2853. if (alwaysLoadConnections)
  2854. {
  2855. loadExternalConnections = true;
  2856. }
  2857. else
  2858. {
  2859. /**/ if (std::strcmp(getCurrentDriverName(), "JACK") != 0)
  2860. loadExternalConnections = true;
  2861. else if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr)
  2862. loadExternalConnections = false;
  2863. else if (std::getenv("LADISH_APP_NAME") != nullptr)
  2864. loadExternalConnections = false;
  2865. else if (std::getenv("NSM_URL") != nullptr)
  2866. loadExternalConnections = false;
  2867. else
  2868. loadExternalConnections = true;
  2869. }
  2870. // plus external connections too
  2871. if (loadExternalConnections)
  2872. {
  2873. bool isExternal;
  2874. loadingAsExternal = hasInternalConnections &&
  2875. (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || isPatchbay);
  2876. for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
  2877. {
  2878. const String& tagName(elem->getTagName());
  2879. // check if we want to load patchbay-mode connections into an external (multi-client) graph
  2880. if (tagName == "Patchbay")
  2881. {
  2882. if (isPatchbay)
  2883. continue;
  2884. isExternal = false;
  2885. loadingAsExternal = true;
  2886. }
  2887. // or load external patchbay connections
  2888. else if (tagName == "ExternalPatchbay")
  2889. {
  2890. if (! isPatchbay)
  2891. loadingAsExternal = true;
  2892. isExternal = true;
  2893. }
  2894. else
  2895. {
  2896. continue;
  2897. }
  2898. water::String sourcePort, targetPort;
  2899. for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement())
  2900. {
  2901. const String& patchTag(patchElem->getTagName());
  2902. if (patchTag != "Connection")
  2903. continue;
  2904. sourcePort.clear();
  2905. targetPort.clear();
  2906. for (XmlElement* connElem = patchElem->getFirstChildElement(); connElem != nullptr; connElem = connElem->getNextElement())
  2907. {
  2908. const String& tag(connElem->getTagName());
  2909. const String text(connElem->getAllSubText().trim());
  2910. /**/ if (tag == "Source")
  2911. sourcePort = xmlSafeString(text, false);
  2912. else if (tag == "Target")
  2913. targetPort = xmlSafeString(text, false);
  2914. }
  2915. if (sourcePort.isNotEmpty() && targetPort.isNotEmpty())
  2916. {
  2917. std::map<water::String, water::String>& map(loadingAsExternal ? mapGroupNamesExternal
  2918. : mapGroupNamesInternal);
  2919. std::map<water::String, water::String>::iterator it;
  2920. if (isExternal && isPatchbay && !loadingAsExternal && sourcePort.startsWith("system:capture_"))
  2921. {
  2922. water::String internalPort = sourcePort.trimCharactersAtStart("system:capture_");
  2923. if (pData->graph.getNumAudioOuts() < 3)
  2924. {
  2925. /**/ if (internalPort == "1")
  2926. internalPort = "Audio Input:Left";
  2927. else if (internalPort == "2")
  2928. internalPort = "Audio Input:Right";
  2929. else if (internalPort == "3")
  2930. internalPort = "Audio Input:Sidechain";
  2931. else
  2932. continue;
  2933. }
  2934. else
  2935. {
  2936. internalPort = "Audio Input:Capture " + internalPort;
  2937. }
  2938. carla_stdout("Converted port name '%s' to '%s' for this session",
  2939. sourcePort.toRawUTF8(), internalPort.toRawUTF8());
  2940. sourcePort = internalPort;
  2941. }
  2942. else if (!isExternal && isMultiClient && sourcePort.startsWith("Audio Input:"))
  2943. {
  2944. water::String externalPort = sourcePort.trimCharactersAtStart("Audio Input:");
  2945. /**/ if (externalPort == "Left")
  2946. externalPort = "system:capture_1";
  2947. else if (externalPort == "Right")
  2948. externalPort = "system:capture_2";
  2949. else if (externalPort == "Sidechain")
  2950. externalPort = "system:capture_3";
  2951. else
  2952. externalPort = "system:capture_ " + externalPort.trimCharactersAtStart("Capture ");
  2953. carla_stdout("Converted port name '%s' to '%s' for this session",
  2954. sourcePort.toRawUTF8(), externalPort.toRawUTF8());
  2955. sourcePort = externalPort;
  2956. }
  2957. else if ((it = map.find(sourcePort.upToFirstOccurrenceOf(":", false, false))) != map.end())
  2958. {
  2959. sourcePort = it->second + sourcePort.fromFirstOccurrenceOf(":", true, false);
  2960. }
  2961. if (isExternal && isPatchbay && !loadingAsExternal && targetPort.startsWith("system:playback_"))
  2962. {
  2963. water::String internalPort = targetPort.trimCharactersAtStart("system:playback_");
  2964. if (pData->graph.getNumAudioOuts() < 3)
  2965. {
  2966. /**/ if (internalPort == "1")
  2967. internalPort = "Audio Output:Left";
  2968. else if (internalPort == "2")
  2969. internalPort = "Audio Output:Right";
  2970. else
  2971. continue;
  2972. }
  2973. else
  2974. {
  2975. internalPort = "Audio Input:Playback " + internalPort;
  2976. }
  2977. carla_stdout("Converted port name '%s' to '%s' for this session",
  2978. targetPort.toRawUTF8(), internalPort.toRawUTF8());
  2979. targetPort = internalPort;
  2980. }
  2981. else if (!isExternal && isMultiClient && targetPort.startsWith("Audio Output:"))
  2982. {
  2983. water::String externalPort = targetPort.trimCharactersAtStart("Audio Output:");
  2984. /**/ if (externalPort == "Left")
  2985. externalPort = "system:playback_1";
  2986. else if (externalPort == "Right")
  2987. externalPort = "system:playback_2";
  2988. else
  2989. externalPort = "system:playback_ " + externalPort.trimCharactersAtStart("Playback ");
  2990. carla_stdout("Converted port name '%s' to '%s' for this session",
  2991. targetPort.toRawUTF8(), externalPort.toRawUTF8());
  2992. targetPort = externalPort;
  2993. }
  2994. else if ((it = map.find(targetPort.upToFirstOccurrenceOf(":", false, false))) != map.end())
  2995. {
  2996. targetPort = it->second + targetPort.fromFirstOccurrenceOf(":", true, false);
  2997. }
  2998. restorePatchbayConnection(loadingAsExternal, sourcePort.toRawUTF8(), targetPort.toRawUTF8());
  2999. }
  3000. }
  3001. break;
  3002. }
  3003. }
  3004. #endif
  3005. if (pData->options.resetXruns)
  3006. clearXruns();
  3007. callback(true, true, ENGINE_CALLBACK_PROJECT_LOAD_FINISHED, 0, 0, 0, 0, 0.0f, nullptr);
  3008. callback(true, true, ENGINE_CALLBACK_CANCELABLE_ACTION, 0, 0, 0, 0, 0.0f, "Loading project");
  3009. carla_debug("CarlaEngine::loadProjectInternal(%p, %s) - END", &xmlDoc, bool2str(alwaysLoadConnections));
  3010. return true;
  3011. #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH
  3012. // unused
  3013. (void)alwaysLoadConnections;
  3014. #endif
  3015. }
  3016. // -----------------------------------------------------------------------
  3017. CARLA_BACKEND_END_NAMESPACE