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

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