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

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