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

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