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.

CarlaEngineNative.cpp 99KB

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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842
  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2020 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaDefines.h"
  18. #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH
  19. # error This file should not be compiled if building alternative-arch bridges
  20. #endif
  21. #include "CarlaEngineInit.hpp"
  22. #include "CarlaEngineInternal.hpp"
  23. #include "CarlaPlugin.hpp"
  24. #include "CarlaBackendUtils.hpp"
  25. #include "CarlaBase64Utils.hpp"
  26. #include "CarlaBinaryUtils.hpp"
  27. #include "CarlaMathUtils.hpp"
  28. #include "CarlaStateUtils.hpp"
  29. #include "CarlaExternalUI.hpp"
  30. #include "CarlaHost.h"
  31. #include "CarlaNative.hpp"
  32. #include "CarlaNativePlugin.h"
  33. #if defined(USING_JUCE) && ! (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
  34. # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
  35. # pragma GCC diagnostic push
  36. # pragma GCC diagnostic ignored "-Wconversion"
  37. # pragma GCC diagnostic ignored "-Weffc++"
  38. # pragma GCC diagnostic ignored "-Wsign-conversion"
  39. # pragma GCC diagnostic ignored "-Wundef"
  40. # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
  41. # endif
  42. # include "AppConfig.h"
  43. # include "juce_events/juce_events.h"
  44. # define USE_JUCE_MESSAGE_THREAD
  45. # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
  46. # pragma GCC diagnostic pop
  47. # endif
  48. #endif
  49. #include "water/files/File.h"
  50. #include "water/streams/MemoryOutputStream.h"
  51. #include "water/xml/XmlDocument.h"
  52. #include "water/xml/XmlElement.h"
  53. using water::File;
  54. using water::MemoryOutputStream;
  55. using water::String;
  56. using water::XmlDocument;
  57. using water::XmlElement;
  58. CARLA_BACKEND_START_NAMESPACE
  59. static const uint32_t kNumInParams = 100;
  60. static const uint32_t kNumOutParams = 10;
  61. static const uint16_t kUiWidth = 1024;
  62. static const uint16_t kUiHeight = 712;
  63. // -----------------------------------------------------------------------
  64. #ifdef USE_JUCE_MESSAGE_THREAD
  65. static int numScopedInitInstances = 0;
  66. class SharedJuceMessageThread : public juce::Thread
  67. {
  68. public:
  69. SharedJuceMessageThread()
  70. : juce::Thread ("SharedJuceMessageThread"),
  71. initialised (false) {}
  72. ~SharedJuceMessageThread()
  73. {
  74. CARLA_SAFE_ASSERT(numScopedInitInstances == 0);
  75. // in case something fails
  76. juce::MessageManager::getInstance()->stopDispatchLoop();
  77. waitForThreadToExit (5000);
  78. }
  79. void incRef()
  80. {
  81. if (numScopedInitInstances++ == 0)
  82. {
  83. startThread (7);
  84. while (! initialised)
  85. juce::Thread::sleep (1);
  86. }
  87. }
  88. void decRef()
  89. {
  90. if (--numScopedInitInstances == 0)
  91. {
  92. juce::MessageManager::getInstance()->stopDispatchLoop();
  93. waitForThreadToExit (5000);
  94. }
  95. }
  96. protected:
  97. void run() override
  98. {
  99. const juce::ScopedJuceInitialiser_GUI juceInitialiser;
  100. juce::MessageManager::getInstance()->setCurrentThreadAsMessageThread();
  101. initialised = true;
  102. juce::MessageManager::getInstance()->runDispatchLoop();
  103. }
  104. private:
  105. volatile bool initialised;
  106. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SharedJuceMessageThread);
  107. };
  108. #endif
  109. // -----------------------------------------------------------------------
  110. class CarlaEngineNative;
  111. class CarlaEngineNativeUI : public CarlaExternalUI
  112. {
  113. public:
  114. CarlaEngineNativeUI(CarlaEngineNative* const engine)
  115. : fEngine(engine)
  116. {
  117. carla_debug("CarlaEngineNativeUI::CarlaEngineNativeUI(%p)", engine);
  118. }
  119. ~CarlaEngineNativeUI() noexcept override
  120. {
  121. carla_debug("CarlaEngineNativeUI::~CarlaEngineNativeUI()");
  122. }
  123. protected:
  124. bool msgReceived(const char* const msg) noexcept override;
  125. private:
  126. CarlaEngineNative* const fEngine;
  127. void _updateParamValues(const CarlaPluginPtr& plugin,
  128. uint32_t pluginId,
  129. bool sendCallback, bool sendPluginHost) const noexcept;
  130. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNativeUI)
  131. };
  132. // -----------------------------------------------------------------------
  133. class CarlaEngineNative : public CarlaEngine
  134. {
  135. public:
  136. CarlaEngineNative(const NativeHostDescriptor* const host, const bool isPatchbay, const bool withMidiOut,
  137. const uint32_t inChan = 2, uint32_t outChan = 2,
  138. const uint32_t cvIns = 0, const uint32_t cvOuts = 0)
  139. : CarlaEngine(),
  140. pHost(host),
  141. #ifdef USE_JUCE_MESSAGE_THREAD
  142. // if not running inside Carla, we will have to run event loop ourselves
  143. kNeedsJuceMsgThread(host->dispatcher(pHost->handle,
  144. NATIVE_HOST_OPCODE_INTERNAL_PLUGIN, 0, 0, nullptr, 0.0f) == 0),
  145. fJuceMsgThread(),
  146. #endif
  147. kIsPatchbay(isPatchbay),
  148. kHasMidiOut(withMidiOut),
  149. fIsActive(false),
  150. fIsRunning(false),
  151. fUiServer(this),
  152. fLastScaleFactor(1.0f),
  153. fLastProjectFolder(),
  154. fPluginDeleterMutex(),
  155. fOptionsForced(false)
  156. {
  157. carla_debug("CarlaEngineNative::CarlaEngineNative()");
  158. carla_zeroFloats(fParameters, kNumInParams+kNumOutParams);
  159. #ifdef USE_JUCE_MESSAGE_THREAD
  160. if (kNeedsJuceMsgThread)
  161. fJuceMsgThread->incRef();
  162. #endif
  163. pData->bufferSize = pHost->get_buffer_size(pHost->handle);
  164. pData->sampleRate = pHost->get_sample_rate(pHost->handle);
  165. pData->initTime(nullptr);
  166. #ifndef BUILD_BRIDGE
  167. // Forced OSC setup when running as plugin
  168. pData->options.oscEnabled = true;
  169. pData->options.oscPortTCP = -1;
  170. pData->options.oscPortUDP = 0;
  171. #endif
  172. if (outChan == 0)
  173. outChan = inChan;
  174. // set-up engine
  175. if (kIsPatchbay)
  176. {
  177. pData->options.processMode = ENGINE_PROCESS_MODE_PATCHBAY;
  178. pData->options.transportMode = ENGINE_TRANSPORT_MODE_PLUGIN;
  179. pData->options.forceStereo = false;
  180. pData->options.preferPluginBridges = false;
  181. pData->options.preferUiBridges = false;
  182. init("Carla-Patchbay");
  183. pData->graph.create(inChan, outChan, cvIns, cvOuts);
  184. }
  185. else
  186. {
  187. CARLA_SAFE_ASSERT(inChan == 2);
  188. CARLA_SAFE_ASSERT(outChan == 2);
  189. pData->options.processMode = ENGINE_PROCESS_MODE_CONTINUOUS_RACK;
  190. pData->options.transportMode = ENGINE_TRANSPORT_MODE_PLUGIN;
  191. pData->options.forceStereo = true;
  192. pData->options.preferPluginBridges = false;
  193. pData->options.preferUiBridges = false;
  194. init("Carla-Rack");
  195. pData->graph.create(0, 0, 0, 0); // FIXME?
  196. }
  197. if (pData->options.resourceDir != nullptr)
  198. delete[] pData->options.resourceDir;
  199. if (pData->options.binaryDir != nullptr)
  200. delete[] pData->options.binaryDir;
  201. pData->options.resourceDir = carla_strdup(pHost->resourceDir);
  202. pData->options.binaryDir = carla_strdup(carla_get_library_folder());
  203. }
  204. ~CarlaEngineNative() override
  205. {
  206. CARLA_SAFE_ASSERT(! fIsActive);
  207. carla_debug("CarlaEngineNative::~CarlaEngineNative() - START");
  208. pData->aboutToClose = true;
  209. fIsRunning = false;
  210. removeAllPlugins();
  211. //runPendingRtEvents();
  212. close();
  213. pData->graph.destroy();
  214. #ifdef USE_JUCE_MESSAGE_THREAD
  215. if (kNeedsJuceMsgThread)
  216. fJuceMsgThread->decRef();
  217. #endif
  218. carla_debug("CarlaEngineNative::~CarlaEngineNative() - END");
  219. }
  220. // -------------------------------------
  221. // CarlaEngine virtual calls
  222. bool init(const char* const clientName) override
  223. {
  224. carla_debug("CarlaEngineNative::init(\"%s\")", clientName);
  225. fIsRunning = true;
  226. if (! pData->init(clientName))
  227. {
  228. close();
  229. setLastError("Failed to init internal data");
  230. return false;
  231. }
  232. pData->bufferSize = pHost->get_buffer_size(pHost->handle);
  233. pData->sampleRate = pHost->get_sample_rate(pHost->handle);
  234. return true;
  235. }
  236. bool close() override
  237. {
  238. fIsRunning = false;
  239. CarlaEngine::close();
  240. return true;
  241. }
  242. bool isRunning() const noexcept override
  243. {
  244. return fIsRunning;
  245. }
  246. bool isOffline() const noexcept override
  247. {
  248. return pHost->is_offline(pHost->handle);
  249. }
  250. bool usesConstantBufferSize() const noexcept override
  251. {
  252. // TODO LV2 hosts can report this, till then we allow this
  253. return true;
  254. }
  255. EngineType getType() const noexcept override
  256. {
  257. return kEngineTypePlugin;
  258. }
  259. const char* getCurrentDriverName() const noexcept override
  260. {
  261. return "Plugin";
  262. }
  263. const char* getCurrentProjectFolder() const noexcept override
  264. {
  265. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  266. static char filetype[] = "carla\0";
  267. try {
  268. return (const char*)(uintptr_t)pHost->dispatcher(pHost->handle,
  269. NATIVE_HOST_OPCODE_GET_FILE_PATH,
  270. 0, 0,
  271. (void*)filetype,
  272. 0.0f);
  273. } CARLA_SAFE_EXCEPTION_RETURN("get_file_path", nullptr);
  274. }
  275. void callback(const bool sendHost, const bool sendOsc,
  276. const EngineCallbackOpcode action, const uint pluginId,
  277. const int value1, const int value2, const int value3,
  278. const float valuef, const char* const valueStr) noexcept override
  279. {
  280. CarlaEngine::callback(sendHost, sendOsc, action, pluginId, value1, value2, value3, valuef, valueStr);
  281. if (sendHost)
  282. uiServerCallback(action, pluginId, value1, value2, value3, valuef, valueStr);
  283. switch (action)
  284. {
  285. case ENGINE_CALLBACK_IDLE:
  286. if (! pData->aboutToClose)
  287. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_HOST_IDLE, 0, 0, nullptr, 0.0f);
  288. break;
  289. case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED:
  290. if (sendHost && value1 >= 0)
  291. {
  292. uint32_t rindex = static_cast<uint32_t>(value1);
  293. if (_getRealIndexForPluginParameter(pluginId, rindex))
  294. {
  295. fParameters[rindex] = valuef;
  296. pHost->ui_parameter_changed(pHost->handle, rindex, valuef);
  297. }
  298. }
  299. break;
  300. default:
  301. break;
  302. }
  303. }
  304. const char* runFileCallback(FileCallbackOpcode action,
  305. bool isDir, const char* title, const char* filter) noexcept override
  306. {
  307. switch (action)
  308. {
  309. case FILE_CALLBACK_DEBUG:
  310. return nullptr;
  311. case FILE_CALLBACK_OPEN:
  312. return pHost->ui_open_file(pHost->handle, isDir, title, filter);
  313. case FILE_CALLBACK_SAVE:
  314. return pHost->ui_save_file(pHost->handle, isDir, title, filter);
  315. }
  316. return nullptr;
  317. }
  318. // -------------------------------------------------------------------
  319. void touchPluginParameter(const uint id, const uint32_t parameterId, const bool touch) noexcept override
  320. {
  321. setParameterTouchFromUI(id, parameterId, touch);
  322. }
  323. // -------------------------------------------------------------------
  324. void setParameterValueFromUI(const uint32_t pluginId, const uint32_t index, const float value)
  325. {
  326. uint32_t rindex = index;
  327. if (_getRealIndexForPluginParameter(pluginId, rindex))
  328. {
  329. fParameters[rindex] = value;
  330. pHost->ui_parameter_changed(pHost->handle, rindex, value);
  331. }
  332. }
  333. void setParameterTouchFromUI(const uint32_t pluginId, const uint32_t index, const bool touch)
  334. {
  335. uint32_t rindex = index;
  336. if (_getRealIndexForPluginParameter(pluginId, rindex))
  337. {
  338. pHost->dispatcher(pHost->handle,
  339. NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER,
  340. static_cast<int32_t>(rindex),
  341. touch ? 1 : 0,
  342. nullptr, 0.0f);
  343. }
  344. }
  345. void reloadFromUI()
  346. {
  347. carla_zeroFloats(fParameters, kNumInParams+kNumOutParams);
  348. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_RELOAD_PARAMETERS, 0, 0, nullptr, 0.0f);
  349. }
  350. protected:
  351. // -------------------------------------------------------------------
  352. void bufferSizeChanged(const uint32_t newBufferSize)
  353. {
  354. if (pData->bufferSize == newBufferSize)
  355. return;
  356. {
  357. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  358. if (fUiServer.writeMessage("buffer-size\n"))
  359. {
  360. char tmpBuf[STR_MAX+1];
  361. carla_zeroChars(tmpBuf, STR_MAX+1);
  362. std::snprintf(tmpBuf, STR_MAX, "%i\n", newBufferSize);
  363. if (fUiServer.writeMessage(tmpBuf))
  364. fUiServer.flushMessages();
  365. }
  366. }
  367. pData->bufferSize = newBufferSize;
  368. CarlaEngine::bufferSizeChanged(newBufferSize);
  369. }
  370. void sampleRateChanged(const double newSampleRate)
  371. {
  372. if (carla_isEqual(pData->sampleRate, newSampleRate))
  373. return;
  374. {
  375. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  376. if (fUiServer.writeMessage("sample-rate\n"))
  377. {
  378. char tmpBuf[STR_MAX+1];
  379. carla_zeroChars(tmpBuf, STR_MAX+1);
  380. {
  381. const CarlaScopedLocale csl;
  382. std::snprintf(tmpBuf, STR_MAX, "%.12g\n", newSampleRate);
  383. }
  384. if (fUiServer.writeMessage(tmpBuf))
  385. fUiServer.flushMessages();
  386. }
  387. }
  388. pData->sampleRate = newSampleRate;
  389. CarlaEngine::sampleRateChanged(newSampleRate);
  390. }
  391. // -------------------------------------------------------------------
  392. void uiServerSendPluginInfo(const CarlaPluginPtr& plugin)
  393. {
  394. char tmpBuf[STR_MAX+1];
  395. carla_zeroChars(tmpBuf, STR_MAX+1);
  396. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  397. const uint pluginId(plugin->getId());
  398. std::snprintf(tmpBuf, STR_MAX, "PLUGIN_INFO_%i\n", pluginId);
  399. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  400. std::snprintf(tmpBuf, STR_MAX, "%i:%i:%i:" P_INT64 ":%i:%i\n",
  401. plugin->getType(), plugin->getCategory(),
  402. plugin->getHints(), plugin->getUniqueId(),
  403. plugin->getOptionsAvailable(), plugin->getOptionsEnabled());
  404. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  405. if (const char* const filename = plugin->getFilename())
  406. {
  407. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(filename),);
  408. }
  409. else
  410. {
  411. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  412. }
  413. if (const char* const name = plugin->getName())
  414. {
  415. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(name),);
  416. }
  417. else
  418. {
  419. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  420. }
  421. if (const char* const iconName = plugin->getIconName())
  422. {
  423. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(iconName),);
  424. }
  425. else
  426. {
  427. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  428. }
  429. if (plugin->getRealName(tmpBuf)) {
  430. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),);
  431. } else {
  432. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  433. }
  434. if (plugin->getLabel(tmpBuf)) {
  435. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),);
  436. } else {
  437. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  438. }
  439. if (plugin->getMaker(tmpBuf)) {
  440. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),);
  441. } else {
  442. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  443. }
  444. if (plugin->getCopyright(tmpBuf)) {
  445. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),);
  446. } else {
  447. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  448. }
  449. std::snprintf(tmpBuf, STR_MAX, "AUDIO_COUNT_%i:%i:%i\n",
  450. pluginId, plugin->getAudioInCount(), plugin->getAudioOutCount());
  451. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  452. std::snprintf(tmpBuf, STR_MAX, "MIDI_COUNT_%i:%i:%i\n",
  453. pluginId, plugin->getMidiInCount(), plugin->getMidiOutCount());
  454. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  455. fUiServer.flushMessages();
  456. }
  457. void uiServerSendPluginParameters(const CarlaPluginPtr& plugin)
  458. {
  459. char tmpBuf[STR_MAX+1];
  460. carla_zeroChars(tmpBuf, STR_MAX+1);
  461. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  462. const CarlaScopedLocale csl;
  463. const uint pluginId(plugin->getId());
  464. for (int32_t i=PARAMETER_ACTIVE; i>PARAMETER_MAX; --i)
  465. {
  466. std::snprintf(tmpBuf, STR_MAX, "PARAMVAL_%u:%i\n", pluginId, i);
  467. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  468. std::snprintf(tmpBuf, STR_MAX, "%.12g\n", static_cast<double>(plugin->getInternalParameterValue(i)));
  469. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  470. fUiServer.flushMessages();
  471. }
  472. uint32_t ins, outs, count;
  473. plugin->getParameterCountInfo(ins, outs);
  474. count = plugin->getParameterCount();
  475. std::snprintf(tmpBuf, STR_MAX, "PARAMETER_COUNT_%i:%i:%i:%i\n", pluginId, ins, outs, count);
  476. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  477. for (uint32_t i=0; i<count; ++i)
  478. {
  479. const ParameterData& paramData(plugin->getParameterData(i));
  480. const ParameterRanges& paramRanges(plugin->getParameterRanges(i));
  481. std::snprintf(tmpBuf, STR_MAX, "PARAMETER_DATA_%i:%i\n", pluginId, i);
  482. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  483. std::snprintf(tmpBuf, STR_MAX, "%i:%i:%i:%i\n", paramData.type, paramData.hints,
  484. paramData.mappedControlIndex, paramData.midiChannel);
  485. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  486. std::snprintf(tmpBuf, STR_MAX, "%.12g:%.12g\n", static_cast<double>(paramData.mappedMinimum),
  487. static_cast<double>(paramData.mappedMaximum));
  488. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  489. if (plugin->getParameterName(i, tmpBuf)) {
  490. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),);
  491. } else {
  492. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  493. }
  494. if (plugin->getParameterUnit(i, tmpBuf)) {
  495. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),);
  496. } else {
  497. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  498. }
  499. if (plugin->getParameterComment(i, tmpBuf)) {
  500. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),);
  501. } else {
  502. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  503. }
  504. if (plugin->getParameterGroupName(i, tmpBuf)) {
  505. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),);
  506. } else {
  507. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  508. }
  509. std::snprintf(tmpBuf, STR_MAX, "PARAMETER_RANGES_%i:%i\n", pluginId, i);
  510. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  511. std::snprintf(tmpBuf, STR_MAX, "%.12g:%.12g:%.12g:%.12g:%.12g:%.12g\n",
  512. static_cast<double>(paramRanges.def),
  513. static_cast<double>(paramRanges.min),
  514. static_cast<double>(paramRanges.max),
  515. static_cast<double>(paramRanges.step),
  516. static_cast<double>(paramRanges.stepSmall),
  517. static_cast<double>(paramRanges.stepLarge));
  518. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  519. std::snprintf(tmpBuf, STR_MAX, "PARAMVAL_%u:%u\n", pluginId, i);
  520. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  521. std::snprintf(tmpBuf, STR_MAX, "%.12g\n", static_cast<double>(plugin->getParameterValue(i)));
  522. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  523. }
  524. fUiServer.flushMessages();
  525. }
  526. void uiServerSendPluginPrograms(const CarlaPluginPtr& plugin)
  527. {
  528. char tmpBuf[STR_MAX+1];
  529. carla_zeroChars(tmpBuf, STR_MAX+1);
  530. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  531. const uint pluginId(plugin->getId());
  532. uint32_t count = plugin->getProgramCount();
  533. std::snprintf(tmpBuf, STR_MAX, "PROGRAM_COUNT_%i:%i:%i\n", pluginId, count, plugin->getCurrentProgram());
  534. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  535. for (uint32_t i=0; i<count; ++i)
  536. {
  537. std::snprintf(tmpBuf, STR_MAX, "PROGRAM_NAME_%i:%i\n", pluginId, i);
  538. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  539. if (plugin->getProgramName(i, tmpBuf)) {
  540. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),);
  541. } else {
  542. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  543. }
  544. }
  545. fUiServer.flushMessages();
  546. count = plugin->getMidiProgramCount();
  547. std::snprintf(tmpBuf, STR_MAX, "MIDI_PROGRAM_COUNT_%i:%i:%i\n",
  548. pluginId, count, plugin->getCurrentMidiProgram());
  549. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  550. for (uint32_t i=0; i<count; ++i)
  551. {
  552. std::snprintf(tmpBuf, STR_MAX, "MIDI_PROGRAM_DATA_%i:%i\n", pluginId, i);
  553. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  554. const MidiProgramData& mpData(plugin->getMidiProgramData(i));
  555. std::snprintf(tmpBuf, STR_MAX, "%i:%i\n", mpData.bank, mpData.program);
  556. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  557. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(mpData.name),);
  558. }
  559. fUiServer.flushMessages();
  560. }
  561. void uiServerSendPluginProperties(const CarlaPluginPtr& plugin)
  562. {
  563. char tmpBuf[STR_MAX+1];
  564. carla_zeroChars(tmpBuf, STR_MAX+1);
  565. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  566. const uint pluginId(plugin->getId());
  567. uint32_t count = plugin->getCustomDataCount();
  568. std::snprintf(tmpBuf, STR_MAX, "CUSTOM_DATA_COUNT_%i:%i\n", pluginId, count);
  569. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  570. for (uint32_t i=0; i<count; ++i)
  571. {
  572. const CustomData& customData(plugin->getCustomData(i));
  573. CARLA_SAFE_ASSERT_CONTINUE(customData.isValid());
  574. if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_PROPERTY) != 0)
  575. continue;
  576. std::snprintf(tmpBuf, STR_MAX, "CUSTOM_DATA_%i:%i\n", pluginId, i);
  577. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  578. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(customData.type),);
  579. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(customData.key),);
  580. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(customData.value),);
  581. }
  582. fUiServer.flushMessages();
  583. }
  584. void uiServerCallback(const EngineCallbackOpcode action, const uint pluginId,
  585. const int value1, const int value2, const int value3,
  586. const float valuef, const char* const valueStr)
  587. {
  588. if (! fIsRunning)
  589. return;
  590. if (! fUiServer.isPipeRunning())
  591. return;
  592. switch (action)
  593. {
  594. case ENGINE_CALLBACK_UPDATE:
  595. if (const CarlaPluginPtr plugin = getPlugin(pluginId))
  596. {
  597. if (plugin->isEnabled())
  598. {
  599. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  600. uiServerSendPluginProperties(plugin);
  601. }
  602. }
  603. break;
  604. case ENGINE_CALLBACK_RELOAD_INFO:
  605. if (const CarlaPluginPtr plugin = getPlugin(pluginId))
  606. {
  607. if (plugin->isEnabled())
  608. {
  609. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  610. uiServerSendPluginInfo(plugin);
  611. }
  612. }
  613. break;
  614. case ENGINE_CALLBACK_RELOAD_PARAMETERS:
  615. if (const CarlaPluginPtr plugin = getPlugin(pluginId))
  616. {
  617. if (plugin->isEnabled())
  618. {
  619. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  620. uiServerSendPluginParameters(plugin);
  621. }
  622. }
  623. break;
  624. case ENGINE_CALLBACK_RELOAD_PROGRAMS:
  625. if (const CarlaPluginPtr plugin = getPlugin(pluginId))
  626. {
  627. if (plugin->isEnabled())
  628. {
  629. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  630. uiServerSendPluginPrograms(plugin);
  631. }
  632. }
  633. break;
  634. case ENGINE_CALLBACK_RELOAD_ALL:
  635. case ENGINE_CALLBACK_PLUGIN_ADDED:
  636. case ENGINE_CALLBACK_PLUGIN_RENAMED:
  637. if (const CarlaPluginPtr plugin = getPlugin(pluginId))
  638. {
  639. if (plugin->isEnabled())
  640. {
  641. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  642. uiServerSendPluginInfo(plugin);
  643. uiServerSendPluginParameters(plugin);
  644. uiServerSendPluginPrograms(plugin);
  645. uiServerSendPluginProperties(plugin);
  646. }
  647. }
  648. break;
  649. default:
  650. break;
  651. }
  652. char tmpBuf[STR_MAX+1];
  653. carla_zeroChars(tmpBuf, STR_MAX+1);
  654. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  655. std::snprintf(tmpBuf, STR_MAX, "ENGINE_CALLBACK_%i\n", int(action));
  656. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  657. std::snprintf(tmpBuf, STR_MAX, "%u\n", pluginId);
  658. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  659. std::snprintf(tmpBuf, STR_MAX, "%i\n", value1);
  660. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  661. std::snprintf(tmpBuf, STR_MAX, "%i\n", value2);
  662. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  663. std::snprintf(tmpBuf, STR_MAX, "%i\n", value3);
  664. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  665. {
  666. const CarlaScopedLocale csl;
  667. std::snprintf(tmpBuf, STR_MAX, "%.12g\n", static_cast<double>(valuef));
  668. }
  669. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  670. if (valueStr != nullptr) {
  671. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(valueStr),);
  672. } else {
  673. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),);
  674. }
  675. fUiServer.flushMessages();
  676. }
  677. void uiServerInfo()
  678. {
  679. CARLA_SAFE_ASSERT_RETURN(fIsRunning,);
  680. CARLA_SAFE_ASSERT_RETURN(fUiServer.isPipeRunning(),);
  681. char tmpBuf[STR_MAX+1];
  682. carla_zeroChars(tmpBuf, STR_MAX+1);
  683. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  684. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
  685. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("osc-urls\n"),);
  686. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(pData->osc.getServerPathTCP()),);
  687. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(pData->osc.getServerPathUDP()),);
  688. #endif
  689. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("max-plugin-number\n"),);
  690. std::snprintf(tmpBuf, STR_MAX, "%i\n", pData->maxPluginNumber);
  691. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  692. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("buffer-size\n"),);
  693. std::snprintf(tmpBuf, STR_MAX, "%i\n", pData->bufferSize);
  694. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  695. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("sample-rate\n"),);
  696. {
  697. const CarlaScopedLocale csl;
  698. std::snprintf(tmpBuf, STR_MAX, "%.12g\n", pData->sampleRate);
  699. }
  700. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  701. fUiServer.flushMessages();
  702. }
  703. void uiServerOptions()
  704. {
  705. CARLA_SAFE_ASSERT_RETURN(fIsRunning,);
  706. CARLA_SAFE_ASSERT_RETURN(fUiServer.isPipeRunning(),);
  707. char tmpBuf[STR_MAX+1];
  708. carla_zeroChars(tmpBuf, STR_MAX+1);
  709. const EngineOptions& options(pData->options);
  710. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  711. const char* const optionsForcedStr(fOptionsForced ? "true\n" : "false\n");
  712. const std::size_t optionsForcedStrSize(fOptionsForced ? 5 : 6);
  713. std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PROCESS_MODE);
  714. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  715. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),);
  716. std::snprintf(tmpBuf, STR_MAX, "%i\n", options.processMode);
  717. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  718. fUiServer.flushMessages();
  719. std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_TRANSPORT_MODE);
  720. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  721. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),);
  722. std::snprintf(tmpBuf, STR_MAX, "%i\n", options.transportMode);
  723. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  724. fUiServer.flushMessages();
  725. std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_FORCE_STEREO);
  726. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  727. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),);
  728. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(options.forceStereo ? "true\n" : "false\n"),);
  729. fUiServer.flushMessages();
  730. std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PREFER_PLUGIN_BRIDGES);
  731. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  732. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),);
  733. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(options.preferPluginBridges ? "true\n" : "false\n"),);
  734. fUiServer.flushMessages();
  735. std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PREFER_UI_BRIDGES);
  736. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  737. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),);
  738. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(options.preferUiBridges ? "true\n" : "false\n"),);
  739. fUiServer.flushMessages();
  740. std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_UIS_ALWAYS_ON_TOP);
  741. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  742. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),);
  743. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(options.uisAlwaysOnTop ? "true\n" : "false\n"),);
  744. fUiServer.flushMessages();
  745. std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_MAX_PARAMETERS);
  746. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  747. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),);
  748. std::snprintf(tmpBuf, STR_MAX, "%i\n", options.maxParameters);
  749. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  750. fUiServer.flushMessages();
  751. std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_UI_BRIDGES_TIMEOUT);
  752. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  753. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize),);
  754. std::snprintf(tmpBuf, STR_MAX, "%i\n", options.uiBridgesTimeout);
  755. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  756. fUiServer.flushMessages();
  757. std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PATH_BINARIES);
  758. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  759. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("true\n", 5),);
  760. std::snprintf(tmpBuf, STR_MAX, "%s\n", options.binaryDir);
  761. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  762. fUiServer.flushMessages();
  763. std::snprintf(tmpBuf, STR_MAX, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PATH_RESOURCES);
  764. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  765. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("true\n", 5),);
  766. std::snprintf(tmpBuf, STR_MAX, "%s\n", options.resourceDir);
  767. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  768. fUiServer.flushMessages();
  769. }
  770. // -------------------------------------------------------------------
  771. // Plugin parameter calls
  772. uint32_t getParameterCount() const
  773. {
  774. return kNumInParams + kNumOutParams;
  775. }
  776. const NativeParameter* getParameterInfo(const uint32_t index) const
  777. {
  778. static NativeParameter param;
  779. static char strBufName[STR_MAX+1];
  780. static char strBufUnit[STR_MAX+1];
  781. static char strBufComment[STR_MAX+1];
  782. static char strBufGroupName[STR_MAX+1];
  783. carla_zeroChars(strBufName, STR_MAX+1);
  784. carla_zeroChars(strBufUnit, STR_MAX+1);
  785. carla_zeroChars(strBufComment, STR_MAX+1);
  786. carla_zeroChars(strBufGroupName, STR_MAX+1);
  787. uint32_t rindex = index;
  788. if (const CarlaPluginPtr plugin = _getPluginForParameterIndex(rindex))
  789. {
  790. const ParameterData& paramData(plugin->getParameterData(rindex));
  791. const ParameterRanges& paramRanges(plugin->getParameterRanges(rindex));
  792. if (! plugin->getParameterName(rindex, strBufName))
  793. strBufName[0] = '\0';
  794. if (! plugin->getParameterUnit(rindex, strBufUnit))
  795. strBufUnit[0] = '\0';
  796. if (! plugin->getParameterComment(rindex, strBufComment))
  797. strBufComment[0] = '\0';
  798. if (! plugin->getParameterGroupName(rindex, strBufGroupName))
  799. std::snprintf(strBufGroupName, STR_MAX, "%u:%s", plugin->getId(), plugin->getName());
  800. uint hints = 0x0;
  801. if (paramData.hints & PARAMETER_IS_BOOLEAN)
  802. hints |= NATIVE_PARAMETER_IS_BOOLEAN;
  803. if (paramData.hints & PARAMETER_IS_INTEGER)
  804. hints |= NATIVE_PARAMETER_IS_INTEGER;
  805. if (paramData.hints & PARAMETER_IS_LOGARITHMIC)
  806. hints |= NATIVE_PARAMETER_IS_LOGARITHMIC;
  807. if (paramData.hints & PARAMETER_IS_AUTOMABLE)
  808. hints |= NATIVE_PARAMETER_IS_AUTOMABLE;
  809. if (paramData.hints & PARAMETER_USES_SAMPLERATE)
  810. hints |= NATIVE_PARAMETER_USES_SAMPLE_RATE;
  811. if (paramData.hints & PARAMETER_USES_SCALEPOINTS)
  812. hints |= NATIVE_PARAMETER_USES_SCALEPOINTS;
  813. if (paramData.type == PARAMETER_INPUT || paramData.type == PARAMETER_OUTPUT)
  814. {
  815. if (paramData.hints & PARAMETER_IS_ENABLED)
  816. hints |= NATIVE_PARAMETER_IS_ENABLED;
  817. if (paramData.type == PARAMETER_OUTPUT)
  818. hints |= NATIVE_PARAMETER_IS_OUTPUT;
  819. }
  820. param.hints = static_cast<NativeParameterHints>(hints);
  821. param.name = strBufName;
  822. param.unit = strBufUnit;
  823. param.comment = strBufComment;
  824. param.groupName = strBufGroupName;
  825. param.ranges.def = paramRanges.def;
  826. param.ranges.min = paramRanges.min;
  827. param.ranges.max = paramRanges.max;
  828. param.ranges.step = paramRanges.step;
  829. param.ranges.stepSmall = paramRanges.stepSmall;
  830. param.ranges.stepLarge = paramRanges.stepLarge;
  831. param.scalePointCount = 0; // TODO
  832. param.scalePoints = nullptr;
  833. return &param;
  834. }
  835. param.hints = index < kNumInParams ? static_cast<NativeParameterHints>(0x0) : NATIVE_PARAMETER_IS_OUTPUT;
  836. param.name = "Unused";
  837. param.unit = "";
  838. param.ranges.def = 0.0f;
  839. param.ranges.min = 0.0f;
  840. param.ranges.max = 1.0f;
  841. param.ranges.step = 0.01f;
  842. param.ranges.stepSmall = 0.001f;
  843. param.ranges.stepLarge = 0.1f;
  844. param.scalePointCount = 0;
  845. param.scalePoints = nullptr;
  846. return &param;
  847. }
  848. float getParameterValue(const uint32_t index) const
  849. {
  850. uint32_t rindex = index;
  851. if (const CarlaPluginPtr plugin = _getPluginForParameterIndex(rindex))
  852. return plugin->getParameterValue(rindex);
  853. return fParameters[index];
  854. }
  855. // -------------------------------------------------------------------
  856. // Plugin state calls
  857. void setParameterValue(const uint32_t index, const float value)
  858. {
  859. uint32_t rindex = index;
  860. if (const CarlaPluginPtr plugin = _getPluginForParameterIndex(rindex))
  861. plugin->setParameterValueRT(rindex, value, false);
  862. fParameters[index] = value;
  863. }
  864. // -------------------------------------------------------------------
  865. // Plugin process calls
  866. void activate()
  867. {
  868. #if 0
  869. for (uint i=0; i < pData->curPluginCount; ++i)
  870. {
  871. CarlaPluginPtr plugin = pData->plugins[i].plugin;
  872. if (plugin == nullptr || ! plugin->isEnabled())
  873. continue;
  874. plugin->setActive(true, true, false);
  875. }
  876. #endif
  877. fIsActive = true;
  878. }
  879. void deactivate()
  880. {
  881. fIsActive = false;
  882. #if 0
  883. for (uint i=0; i < pData->curPluginCount; ++i)
  884. {
  885. CarlaPluginPtr plugin = pData->plugins[i].plugin;
  886. if (plugin == nullptr || ! plugin->isEnabled())
  887. continue;
  888. plugin->setActive(false, true, false);
  889. }
  890. #endif
  891. // just in case
  892. //runPendingRtEvents();
  893. }
  894. void process(const float* const* const inBuffer, float** const outBuffer, const uint32_t frames,
  895. const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount)
  896. {
  897. if (frames > pData->bufferSize)
  898. {
  899. carla_stderr2("Host is calling process with too high number of frames! %u vs %u",
  900. frames, pData->bufferSize);
  901. deactivate();
  902. bufferSizeChanged(frames);
  903. activate();
  904. }
  905. const PendingRtEventsRunner prt(this, frames, true);
  906. // ---------------------------------------------------------------
  907. // Time Info
  908. const NativeTimeInfo* const timeInfo(pHost->get_time_info(pHost->handle));
  909. pData->timeInfo.playing = timeInfo->playing;
  910. pData->timeInfo.frame = timeInfo->frame;
  911. pData->timeInfo.usecs = timeInfo->usecs;
  912. pData->timeInfo.bbt.valid = timeInfo->bbt.valid;
  913. if (timeInfo->bbt.valid)
  914. {
  915. pData->timeInfo.bbt.bar = timeInfo->bbt.bar;
  916. pData->timeInfo.bbt.beat = timeInfo->bbt.beat;
  917. pData->timeInfo.bbt.tick = timeInfo->bbt.tick;
  918. pData->timeInfo.bbt.barStartTick = timeInfo->bbt.barStartTick;
  919. pData->timeInfo.bbt.beatsPerBar = timeInfo->bbt.beatsPerBar;
  920. pData->timeInfo.bbt.beatType = timeInfo->bbt.beatType;
  921. pData->timeInfo.bbt.ticksPerBeat = timeInfo->bbt.ticksPerBeat;
  922. pData->timeInfo.bbt.beatsPerMinute = timeInfo->bbt.beatsPerMinute;
  923. }
  924. // ---------------------------------------------------------------
  925. // Do nothing if no plugins and rack mode
  926. if (pData->curPluginCount == 0 && ! kIsPatchbay)
  927. {
  928. if (outBuffer[0] != inBuffer[0])
  929. carla_copyFloats(outBuffer[0], inBuffer[0], frames);
  930. if (outBuffer[1] != inBuffer[1])
  931. carla_copyFloats(outBuffer[1], inBuffer[1], frames);
  932. for (uint32_t i=0; i < midiEventCount; ++i)
  933. {
  934. if (! pHost->write_midi_event(pHost->handle, &midiEvents[i]))
  935. break;
  936. }
  937. return;
  938. }
  939. // ---------------------------------------------------------------
  940. // initialize events
  941. carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount);
  942. carla_zeroStructs(pData->events.out, kMaxEngineEventInternalCount);
  943. // ---------------------------------------------------------------
  944. // events input (before processing)
  945. {
  946. uint32_t engineEventIndex = 0;
  947. for (uint32_t i=0; i < midiEventCount && engineEventIndex < kMaxEngineEventInternalCount; ++i)
  948. {
  949. const NativeMidiEvent& midiEvent(midiEvents[i]);
  950. EngineEvent& engineEvent(pData->events.in[engineEventIndex++]);
  951. engineEvent.time = midiEvent.time;
  952. engineEvent.fillFromMidiData(midiEvent.size, midiEvent.data, 0);
  953. if (engineEventIndex >= kMaxEngineEventInternalCount)
  954. break;
  955. }
  956. }
  957. if (kIsPatchbay)
  958. {
  959. // -----------------------------------------------------------
  960. // process
  961. pData->graph.process(pData, inBuffer, outBuffer, frames);
  962. }
  963. else
  964. {
  965. // -----------------------------------------------------------
  966. // create audio buffers
  967. const float* inBuf[2] = { inBuffer[0], inBuffer[1] };
  968. /* */ float* outBuf[2] = { outBuffer[0], outBuffer[1] };
  969. // -----------------------------------------------------------
  970. // process
  971. pData->graph.processRack(pData, inBuf, outBuf, frames);
  972. }
  973. // ---------------------------------------------------------------
  974. // events output (after processing)
  975. carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount);
  976. if (kHasMidiOut)
  977. {
  978. NativeMidiEvent midiEvent;
  979. for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i)
  980. {
  981. const EngineEvent& engineEvent(pData->events.out[i]);
  982. if (engineEvent.type == kEngineEventTypeNull)
  983. break;
  984. carla_zeroStruct(midiEvent);
  985. midiEvent.time = engineEvent.time;
  986. /**/ if (engineEvent.type == kEngineEventTypeControl)
  987. {
  988. midiEvent.port = 0;
  989. midiEvent.size = engineEvent.ctrl.convertToMidiData(engineEvent.channel, midiEvent.data);
  990. }
  991. else if (engineEvent.type == kEngineEventTypeMidi)
  992. {
  993. if (engineEvent.midi.size > 4)
  994. continue;
  995. midiEvent.port = engineEvent.midi.port;
  996. midiEvent.size = engineEvent.midi.size;
  997. midiEvent.data[0] = static_cast<uint8_t>(engineEvent.midi.data[0] | (engineEvent.channel & MIDI_CHANNEL_BIT));
  998. for (uint8_t j=1; j < midiEvent.size; ++j)
  999. midiEvent.data[j] = engineEvent.midi.data[j];
  1000. }
  1001. else
  1002. {
  1003. continue;
  1004. }
  1005. if (midiEvent.size > 0)
  1006. pHost->write_midi_event(pHost->handle, &midiEvent);
  1007. }
  1008. }
  1009. }
  1010. // -------------------------------------------------------------------
  1011. // Plugin UI calls
  1012. void uiShow(const bool show)
  1013. {
  1014. if (show)
  1015. {
  1016. if (fUiServer.isPipeRunning())
  1017. {
  1018. fUiServer.writeFocusMessage();
  1019. return;
  1020. }
  1021. CarlaString path(pHost->resourceDir);
  1022. if (kIsPatchbay)
  1023. path += CARLA_OS_SEP_STR "carla-plugin-patchbay";
  1024. else
  1025. path += CARLA_OS_SEP_STR "carla-plugin";
  1026. #ifdef CARLA_OS_WIN
  1027. path += ".exe";
  1028. #endif
  1029. carla_stdout("Trying to start carla-plugin using \"%s\"", path.buffer());
  1030. fUiServer.setData(path, pData->sampleRate, pHost->uiName);
  1031. if (! fUiServer.startPipeServer(false))
  1032. {
  1033. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f);
  1034. return;
  1035. }
  1036. uiServerInfo();
  1037. uiServerOptions();
  1038. uiServerCallback(ENGINE_CALLBACK_ENGINE_STARTED,
  1039. pData->curPluginCount,
  1040. pData->options.processMode,
  1041. pData->options.transportMode,
  1042. static_cast<int>(pData->bufferSize),
  1043. static_cast<float>(pData->sampleRate),
  1044. "Plugin");
  1045. fUiServer.writeShowMessage();
  1046. for (uint i=0; i < pData->curPluginCount; ++i)
  1047. {
  1048. if (const CarlaPluginPtr plugin = pData->plugins[i].plugin)
  1049. if (plugin->isEnabled())
  1050. uiServerCallback(ENGINE_CALLBACK_PLUGIN_ADDED, i, 0, 0, 0, 0.0f, plugin->getName());
  1051. }
  1052. if (kIsPatchbay)
  1053. patchbayRefresh(true, false, false);
  1054. }
  1055. else
  1056. {
  1057. fUiServer.stopPipeServer(2000);
  1058. // hide all custom uis
  1059. for (uint i=0; i < pData->curPluginCount; ++i)
  1060. {
  1061. if (const CarlaPluginPtr plugin = pData->plugins[i].plugin)
  1062. {
  1063. if (plugin->isEnabled())
  1064. {
  1065. if (plugin->getHints() & PLUGIN_HAS_CUSTOM_UI)
  1066. {
  1067. try {
  1068. plugin->showCustomUI(false);
  1069. } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin showCustomUI (hide)");
  1070. }
  1071. }
  1072. }
  1073. }
  1074. }
  1075. }
  1076. void uiIdle()
  1077. {
  1078. for (uint i=0; i < pData->curPluginCount; ++i)
  1079. {
  1080. if (const CarlaPluginPtr plugin = pData->plugins[i].plugin)
  1081. {
  1082. if (plugin->isEnabled())
  1083. {
  1084. const uint hints = plugin->getHints();
  1085. if ((hints & PLUGIN_HAS_CUSTOM_UI) != 0 && (hints & PLUGIN_NEEDS_UI_MAIN_THREAD) != 0)
  1086. {
  1087. try {
  1088. plugin->uiIdle();
  1089. } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin uiIdle");
  1090. }
  1091. }
  1092. }
  1093. }
  1094. idlePipe();
  1095. switch (fUiServer.getAndResetUiState())
  1096. {
  1097. case CarlaExternalUI::UiNone:
  1098. case CarlaExternalUI::UiShow:
  1099. break;
  1100. case CarlaExternalUI::UiCrashed:
  1101. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f);
  1102. break;
  1103. case CarlaExternalUI::UiHide:
  1104. pHost->ui_closed(pHost->handle);
  1105. fUiServer.stopPipeServer(1000);
  1106. break;
  1107. }
  1108. if (carla_isNotEqual(fLastScaleFactor, pData->options.uiScale))
  1109. {
  1110. fLastScaleFactor = pData->options.uiScale;
  1111. pHost->dispatcher(pHost->handle,
  1112. NATIVE_HOST_OPCODE_UI_RESIZE,
  1113. static_cast<int>(kUiWidth * fLastScaleFactor + 0.5f),
  1114. static_cast<int>(kUiHeight * fLastScaleFactor + 0.5f),
  1115. nullptr, 0.0f);
  1116. }
  1117. {
  1118. const CarlaMutexLocker cml(fPluginDeleterMutex);
  1119. pData->deletePluginsAsNeeded();
  1120. }
  1121. }
  1122. void uiSetParameterValue(const uint32_t index, const float value)
  1123. {
  1124. uint32_t rindex = index;
  1125. if (const CarlaPluginPtr plugin = _getPluginForParameterIndex(rindex))
  1126. {
  1127. if (plugin->getHints() & PLUGIN_HAS_CUSTOM_UI)
  1128. plugin->uiParameterChange(rindex, value);
  1129. if (index >= kNumInParams || ! fUiServer.isPipeRunning())
  1130. return;
  1131. uiServerCallback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1132. plugin->getId(),
  1133. static_cast<int>(rindex),
  1134. 0, 0,
  1135. value,
  1136. nullptr);
  1137. }
  1138. }
  1139. void idlePipe()
  1140. {
  1141. if (! fUiServer.isPipeRunning())
  1142. return;
  1143. fUiServer.idlePipe();
  1144. if (! fUiServer.isPipeRunning())
  1145. return;
  1146. char tmpBuf[STR_MAX+1];
  1147. carla_zeroChars(tmpBuf, STR_MAX+1);
  1148. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  1149. const CarlaScopedLocale csl;
  1150. const EngineTimeInfo& timeInfo(pData->timeInfo);
  1151. // ------------------------------------------------------------------------------------------------------------
  1152. // send engine info
  1153. std::snprintf(tmpBuf, STR_MAX, "%.12g:0\n", static_cast<double>(getDSPLoad()));
  1154. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("runtime-info\n"),);
  1155. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  1156. fUiServer.flushMessages();
  1157. if (const char* const projFolder = getCurrentProjectFolder())
  1158. {
  1159. if (fLastProjectFolder != projFolder)
  1160. {
  1161. fLastProjectFolder = projFolder;
  1162. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("project-folder\n"),);
  1163. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(projFolder),);
  1164. fUiServer.flushMessages();
  1165. }
  1166. }
  1167. // ------------------------------------------------------------------------------------------------------------
  1168. // send transport
  1169. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("transport\n"),);
  1170. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(timeInfo.playing ? "true\n" : "false\n"),);
  1171. if (timeInfo.bbt.valid)
  1172. {
  1173. std::snprintf(tmpBuf, STR_MAX, P_UINT64 ":%i:%i:%i\n", timeInfo.frame,
  1174. timeInfo.bbt.bar,
  1175. timeInfo.bbt.beat,
  1176. static_cast<int>(timeInfo.bbt.tick + 0.5));
  1177. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  1178. std::snprintf(tmpBuf, STR_MAX, "%.12g\n", timeInfo.bbt.beatsPerMinute);
  1179. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  1180. }
  1181. else
  1182. {
  1183. std::snprintf(tmpBuf, STR_MAX, P_UINT64 ":0:0:0\n", timeInfo.frame);
  1184. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  1185. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage("0.0\n"),);
  1186. }
  1187. fUiServer.flushMessages();
  1188. // ------------------------------------------------------------------------------------------------------------
  1189. // send peaks and param outputs for all plugins
  1190. for (uint i=0; i < pData->curPluginCount; ++i)
  1191. {
  1192. const EnginePluginData& plugData(pData->plugins[i]);
  1193. const CarlaPluginPtr plugin = pData->plugins[i].plugin;
  1194. std::snprintf(tmpBuf, STR_MAX, "PEAKS_%i\n", i);
  1195. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  1196. std::snprintf(tmpBuf, STR_MAX, "%.12g:%.12g:%.12g:%.12g\n",
  1197. static_cast<double>(plugData.peaks[0]),
  1198. static_cast<double>(plugData.peaks[1]),
  1199. static_cast<double>(plugData.peaks[2]),
  1200. static_cast<double>(plugData.peaks[3]));
  1201. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  1202. fUiServer.flushMessages();
  1203. for (uint32_t j=0, count=plugin->getParameterCount(); j < count; ++j)
  1204. {
  1205. if (! plugin->isParameterOutput(j))
  1206. continue;
  1207. std::snprintf(tmpBuf, STR_MAX, "PARAMVAL_%u:%u\n", i, j);
  1208. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  1209. std::snprintf(tmpBuf, STR_MAX, "%.12g\n", static_cast<double>(plugin->getParameterValue(j)));
  1210. CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
  1211. fUiServer.flushMessages();
  1212. }
  1213. }
  1214. }
  1215. // -------------------------------------------------------------------
  1216. // Plugin state calls
  1217. char* getState() const
  1218. {
  1219. MemoryOutputStream out;
  1220. saveProjectInternal(out);
  1221. return strdup(out.toString().toRawUTF8());
  1222. }
  1223. void setState(const char* const data)
  1224. {
  1225. // remove all plugins from UI side
  1226. for (uint i=0, count=pData->curPluginCount; i < count; ++i)
  1227. CarlaEngine::callback(true, true, ENGINE_CALLBACK_PLUGIN_REMOVED, count-i-1, 0, 0, 0, 0.0f, nullptr);
  1228. // remove all plugins from backend, no lock
  1229. fIsRunning = false;
  1230. removeAllPlugins();
  1231. fIsRunning = true;
  1232. {
  1233. const CarlaMutexLocker cml(fPluginDeleterMutex);
  1234. pData->deletePluginsAsNeeded();
  1235. }
  1236. // stopped during removeAllPlugins()
  1237. if (! pData->thread.isThreadRunning())
  1238. pData->thread.startThread();
  1239. fOptionsForced = true;
  1240. const String state(data);
  1241. XmlDocument xml(state);
  1242. loadProjectInternal(xml, true);
  1243. reloadFromUI();
  1244. }
  1245. // -------------------------------------------------------------------
  1246. public:
  1247. #define handlePtr ((CarlaEngineNative*)handle)
  1248. static NativePluginHandle _instantiateRack(const NativeHostDescriptor* host)
  1249. {
  1250. return new CarlaEngineNative(host, false, true);
  1251. }
  1252. static NativePluginHandle _instantiateRackNoMidiOut(const NativeHostDescriptor* host)
  1253. {
  1254. return new CarlaEngineNative(host, false, false);
  1255. }
  1256. static NativePluginHandle _instantiatePatchbay(const NativeHostDescriptor* host)
  1257. {
  1258. return new CarlaEngineNative(host, true, true);
  1259. }
  1260. static NativePluginHandle _instantiatePatchbay3s(const NativeHostDescriptor* host)
  1261. {
  1262. return new CarlaEngineNative(host, true, true, 3, 2);
  1263. }
  1264. static NativePluginHandle _instantiatePatchbay16(const NativeHostDescriptor* host)
  1265. {
  1266. return new CarlaEngineNative(host, true, true, 16, 16);
  1267. }
  1268. static NativePluginHandle _instantiatePatchbay32(const NativeHostDescriptor* host)
  1269. {
  1270. return new CarlaEngineNative(host, true, true, 32, 32);
  1271. }
  1272. static NativePluginHandle _instantiatePatchbay64(const NativeHostDescriptor* host)
  1273. {
  1274. return new CarlaEngineNative(host, true, true, 64, 64);
  1275. }
  1276. static NativePluginHandle _instantiatePatchbayCV(const NativeHostDescriptor* host)
  1277. {
  1278. return new CarlaEngineNative(host, true, true, 2, 2, 5, 5);
  1279. }
  1280. static void _cleanup(NativePluginHandle handle)
  1281. {
  1282. delete handlePtr;
  1283. }
  1284. static uint32_t _get_parameter_count(NativePluginHandle handle)
  1285. {
  1286. return handlePtr->getParameterCount();
  1287. }
  1288. static const NativeParameter* _get_parameter_info(NativePluginHandle handle, uint32_t index)
  1289. {
  1290. return handlePtr->getParameterInfo(index);
  1291. }
  1292. static float _get_parameter_value(NativePluginHandle handle, uint32_t index)
  1293. {
  1294. return handlePtr->getParameterValue(index);
  1295. }
  1296. static void _set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  1297. {
  1298. handlePtr->setParameterValue(index, value);
  1299. }
  1300. static void _ui_show(NativePluginHandle handle, bool show)
  1301. {
  1302. handlePtr->uiShow(show);
  1303. }
  1304. static void _ui_idle(NativePluginHandle handle)
  1305. {
  1306. handlePtr->uiIdle();
  1307. }
  1308. static void _ui_set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  1309. {
  1310. handlePtr->uiSetParameterValue(index, value);
  1311. }
  1312. static void _activate(NativePluginHandle handle)
  1313. {
  1314. handlePtr->activate();
  1315. }
  1316. static void _deactivate(NativePluginHandle handle)
  1317. {
  1318. handlePtr->deactivate();
  1319. }
  1320. // FIXME for v3.0, use const for the input buffer
  1321. static void _process(NativePluginHandle handle,
  1322. float** inBuffer, float** outBuffer, const uint32_t frames,
  1323. const NativeMidiEvent* midiEvents, uint32_t midiEventCount)
  1324. {
  1325. handlePtr->process(inBuffer, outBuffer, frames, midiEvents, midiEventCount);
  1326. }
  1327. static char* _get_state(NativePluginHandle handle)
  1328. {
  1329. return handlePtr->getState();
  1330. }
  1331. static void _set_state(NativePluginHandle handle, const char* data)
  1332. {
  1333. handlePtr->setState(data);
  1334. }
  1335. static intptr_t _dispatcher(NativePluginHandle handle,
  1336. NativePluginDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
  1337. {
  1338. switch(opcode)
  1339. {
  1340. case NATIVE_PLUGIN_OPCODE_NULL:
  1341. return 0;
  1342. case NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
  1343. CARLA_SAFE_ASSERT_RETURN(value > 0, 0);
  1344. handlePtr->bufferSizeChanged(static_cast<uint32_t>(value));
  1345. return 0;
  1346. case NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
  1347. CARLA_SAFE_ASSERT_RETURN(opt > 0.0f, 0);
  1348. handlePtr->sampleRateChanged(static_cast<double>(opt));
  1349. return 0;
  1350. case NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED:
  1351. handlePtr->offlineModeChanged(value != 0);
  1352. return 0;
  1353. case NATIVE_PLUGIN_OPCODE_UI_NAME_CHANGED:
  1354. //handlePtr->uiNameChanged(static_cast<const char*>(ptr));
  1355. return 0;
  1356. case NATIVE_PLUGIN_OPCODE_GET_INTERNAL_HANDLE: {
  1357. CarlaEngineNative* const engine = handlePtr;
  1358. return (intptr_t)(CarlaEngine*)engine;
  1359. }
  1360. case NATIVE_PLUGIN_OPCODE_IDLE:
  1361. //handlePtr->idle();
  1362. return 0;
  1363. }
  1364. return 0;
  1365. // unused
  1366. (void)index;
  1367. (void)ptr;
  1368. }
  1369. // -------------------------------------------------------------------
  1370. #undef handlePtr
  1371. private:
  1372. const NativeHostDescriptor* const pHost;
  1373. #ifdef USE_JUCE_MESSAGE_THREAD
  1374. const bool kNeedsJuceMsgThread;
  1375. const juce::SharedResourcePointer<SharedJuceMessageThread> fJuceMsgThread;
  1376. #endif
  1377. const bool kIsPatchbay; // rack if false
  1378. const bool kHasMidiOut;
  1379. bool fIsActive, fIsRunning;
  1380. CarlaEngineNativeUI fUiServer;
  1381. float fParameters[kNumInParams+kNumOutParams];
  1382. float fLastScaleFactor;
  1383. CarlaString fLastProjectFolder;
  1384. CarlaMutex fPluginDeleterMutex;
  1385. bool fOptionsForced;
  1386. CarlaPluginPtr _getPluginForParameterIndex(uint32_t& index) const noexcept
  1387. {
  1388. if (pData->curPluginCount == 0 || pData->plugins == nullptr)
  1389. return nullptr;
  1390. for (uint32_t i=0; i<pData->curPluginCount; ++i)
  1391. {
  1392. const CarlaPluginPtr plugin = pData->plugins[i].plugin;
  1393. if (plugin.get() == nullptr || ! plugin->isEnabled())
  1394. break;
  1395. if (const uint32_t paramCount = plugin->getParameterCount())
  1396. {
  1397. if (index >= paramCount)
  1398. {
  1399. index -= paramCount;
  1400. continue;
  1401. }
  1402. return plugin;
  1403. }
  1404. }
  1405. return nullptr;
  1406. }
  1407. bool _getRealIndexForPluginParameter(const uint32_t pluginId, uint32_t& rindex) const noexcept
  1408. {
  1409. if (pData->curPluginCount == 0 || pluginId >= pData->curPluginCount || pData->plugins == nullptr)
  1410. return false;
  1411. for (uint32_t i=0; i<pluginId; ++i)
  1412. {
  1413. const CarlaPluginPtr plugin = pData->plugins[i].plugin;
  1414. if (plugin.get() == nullptr || ! plugin->isEnabled())
  1415. return false;
  1416. rindex += plugin->getParameterCount();
  1417. }
  1418. if (rindex >= kNumInParams)
  1419. return false;
  1420. return true;
  1421. }
  1422. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNative)
  1423. };
  1424. // -----------------------------------------------------------------------
  1425. bool CarlaEngineNativeUI::msgReceived(const char* const msg) noexcept
  1426. {
  1427. if (CarlaExternalUI::msgReceived(msg))
  1428. return true;
  1429. bool ok = true;
  1430. if (std::strcmp(msg, "set_engine_option") == 0)
  1431. {
  1432. uint32_t option;
  1433. int32_t value;
  1434. const char* valueStr = nullptr;
  1435. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(option), true);
  1436. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(value), true);
  1437. readNextLineAsString(valueStr, false); // can be null
  1438. try {
  1439. fEngine->setOption(static_cast<EngineOption>(option), value, valueStr);
  1440. } CARLA_SAFE_EXCEPTION("setOption");
  1441. }
  1442. else if (std::strcmp(msg, "clear_engine_xruns") == 0)
  1443. {
  1444. fEngine->clearXruns();
  1445. }
  1446. else if (std::strcmp(msg, "cancel_engine_action") == 0)
  1447. {
  1448. fEngine->setActionCanceled(true);
  1449. }
  1450. else if (std::strcmp(msg, "load_file") == 0)
  1451. {
  1452. const char* filename;
  1453. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename, false), true);
  1454. try {
  1455. ok = fEngine->loadFile(filename);
  1456. } CARLA_SAFE_EXCEPTION("loadFile");
  1457. }
  1458. else if (std::strcmp(msg, "load_project") == 0)
  1459. {
  1460. const char* filename;
  1461. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename, false), true);
  1462. try {
  1463. ok = fEngine->loadProject(filename, true);
  1464. } CARLA_SAFE_EXCEPTION("loadProject");
  1465. }
  1466. else if (std::strcmp(msg, "save_project") == 0)
  1467. {
  1468. const char* filename;
  1469. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename, false), true);
  1470. try {
  1471. ok = fEngine->saveProject(filename, true);
  1472. } CARLA_SAFE_EXCEPTION("saveProject");
  1473. }
  1474. else if (std::strcmp(msg, "clear_project_filename") == 0)
  1475. {
  1476. fEngine->clearCurrentProjectFilename();
  1477. }
  1478. else if (std::strcmp(msg, "patchbay_connect") == 0)
  1479. {
  1480. bool external;
  1481. uint32_t groupA, portA, groupB, portB;
  1482. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(external), true);
  1483. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(groupA), true);
  1484. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(portA), true);
  1485. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(groupB), true);
  1486. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(portB), true);
  1487. try {
  1488. ok = fEngine->patchbayConnect(external, groupA, portA, groupB, portB);
  1489. } CARLA_SAFE_EXCEPTION("patchbayConnect");
  1490. }
  1491. else if (std::strcmp(msg, "patchbay_disconnect") == 0)
  1492. {
  1493. bool external;
  1494. uint32_t connectionId;
  1495. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(external), true);
  1496. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(connectionId), true);
  1497. try {
  1498. ok = fEngine->patchbayDisconnect(external, connectionId);
  1499. } CARLA_SAFE_EXCEPTION("patchbayDisconnect");
  1500. }
  1501. else if (std::strcmp(msg, "patchbay_set_group_pos") == 0)
  1502. {
  1503. bool external;
  1504. uint32_t groupId;
  1505. int x1, y1, x2, y2;
  1506. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(external), true);
  1507. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(groupId), true);
  1508. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(x1), true);
  1509. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(y1), true);
  1510. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(x2), true);
  1511. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(y2), true);
  1512. try {
  1513. ok = fEngine->patchbaySetGroupPos(false, true, external, groupId, x1, y1, x2, y2);
  1514. } CARLA_SAFE_EXCEPTION("patchbaySetGroupPos");
  1515. }
  1516. else if (std::strcmp(msg, "patchbay_refresh") == 0)
  1517. {
  1518. bool external;
  1519. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(external), true);
  1520. try {
  1521. ok = fEngine->patchbayRefresh(true, false, external);
  1522. } CARLA_SAFE_EXCEPTION("patchbayRefresh");
  1523. }
  1524. else if (std::strcmp(msg, "transport_play") == 0)
  1525. {
  1526. fEngine->transportPlay();
  1527. }
  1528. else if (std::strcmp(msg, "transport_pause") == 0)
  1529. {
  1530. fEngine->transportPause();
  1531. }
  1532. else if (std::strcmp(msg, "transport_bpm") == 0)
  1533. {
  1534. double bpm;
  1535. CARLA_SAFE_ASSERT_RETURN(readNextLineAsDouble(bpm), true);
  1536. fEngine->transportBPM(bpm);
  1537. }
  1538. else if (std::strcmp(msg, "transport_relocate") == 0)
  1539. {
  1540. uint64_t frame;
  1541. CARLA_SAFE_ASSERT_RETURN(readNextLineAsULong(frame), true);
  1542. fEngine->transportRelocate(frame);
  1543. }
  1544. else if (std::strcmp(msg, "add_plugin") == 0)
  1545. {
  1546. uint32_t btype, ptype;
  1547. const char* filename = nullptr;
  1548. const char* name;
  1549. const char* label;
  1550. int64_t uniqueId;
  1551. uint options;
  1552. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(btype), true);
  1553. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(ptype), true);
  1554. readNextLineAsString(filename, true); // can be null
  1555. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(name, true), true);
  1556. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(label, true), true);
  1557. CARLA_SAFE_ASSERT_RETURN(readNextLineAsLong(uniqueId), true);
  1558. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(options), true);
  1559. if (filename != nullptr && std::strcmp(filename, "(null)") == 0)
  1560. {
  1561. delete[] filename;
  1562. filename = nullptr;
  1563. }
  1564. if (std::strcmp(name, "(null)") == 0)
  1565. {
  1566. delete[] name;
  1567. name = nullptr;
  1568. }
  1569. ok = fEngine->addPlugin(static_cast<BinaryType>(btype), static_cast<PluginType>(ptype),
  1570. filename, name, label, uniqueId, nullptr, options);
  1571. if (filename != nullptr)
  1572. delete[] filename;
  1573. if (name != nullptr)
  1574. delete[] name;
  1575. delete[] label;
  1576. fEngine->reloadFromUI();
  1577. }
  1578. else if (std::strcmp(msg, "remove_plugin") == 0)
  1579. {
  1580. uint32_t pluginId;
  1581. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1582. ok = fEngine->removePlugin(pluginId);
  1583. fEngine->reloadFromUI();
  1584. }
  1585. else if (std::strcmp(msg, "remove_all_plugins") == 0)
  1586. {
  1587. ok = fEngine->removeAllPlugins();
  1588. fEngine->reloadFromUI();
  1589. }
  1590. else if (std::strcmp(msg, "rename_plugin") == 0)
  1591. {
  1592. uint32_t pluginId;
  1593. const char* newName;
  1594. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1595. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(newName, false), true);
  1596. ok = fEngine->renamePlugin(pluginId, newName);
  1597. }
  1598. else if (std::strcmp(msg, "clone_plugin") == 0)
  1599. {
  1600. uint32_t pluginId;
  1601. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1602. ok = fEngine->clonePlugin(pluginId);
  1603. }
  1604. else if (std::strcmp(msg, "replace_plugin") == 0)
  1605. {
  1606. uint32_t pluginId;
  1607. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1608. ok = fEngine->replacePlugin(pluginId);
  1609. }
  1610. else if (std::strcmp(msg, "switch_plugins") == 0)
  1611. {
  1612. uint32_t pluginIdA, pluginIdB;
  1613. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginIdA), true);
  1614. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginIdB), true);
  1615. ok = fEngine->switchPlugins(pluginIdA, pluginIdB);
  1616. fEngine->reloadFromUI();
  1617. }
  1618. else if (std::strcmp(msg, "load_plugin_state") == 0)
  1619. {
  1620. uint32_t pluginId;
  1621. const char* filename;
  1622. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1623. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename, false), true);
  1624. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1625. {
  1626. plugin->loadStateFromFile(filename);
  1627. _updateParamValues(plugin, pluginId, false, true);
  1628. }
  1629. }
  1630. else if (std::strcmp(msg, "save_plugin_state") == 0)
  1631. {
  1632. uint32_t pluginId;
  1633. const char* filename;
  1634. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1635. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename, false), true);
  1636. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1637. plugin->saveStateToFile(filename);
  1638. }
  1639. else if (std::strcmp(msg, "set_option") == 0)
  1640. {
  1641. uint32_t pluginId, option;
  1642. bool yesNo;
  1643. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1644. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(option), true);
  1645. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo), true);
  1646. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1647. plugin->setOption(option, yesNo, false);
  1648. }
  1649. else if (std::strcmp(msg, "set_active") == 0)
  1650. {
  1651. uint32_t pluginId;
  1652. bool onOff;
  1653. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1654. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(onOff), true);
  1655. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1656. plugin->setActive(onOff, true, false);
  1657. }
  1658. else if (std::strcmp(msg, "set_drywet") == 0)
  1659. {
  1660. uint32_t pluginId;
  1661. float value;
  1662. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1663. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  1664. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1665. plugin->setDryWet(value, true, false);
  1666. }
  1667. else if (std::strcmp(msg, "set_volume") == 0)
  1668. {
  1669. uint32_t pluginId;
  1670. float value;
  1671. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1672. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  1673. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1674. plugin->setVolume(value, true, false);
  1675. }
  1676. else if (std::strcmp(msg, "set_balance_left") == 0)
  1677. {
  1678. uint32_t pluginId;
  1679. float value;
  1680. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1681. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  1682. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1683. plugin->setBalanceLeft(value, true, false);
  1684. }
  1685. else if (std::strcmp(msg, "set_balance_right") == 0)
  1686. {
  1687. uint32_t pluginId;
  1688. float value;
  1689. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1690. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  1691. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1692. plugin->setBalanceRight(value, true, false);
  1693. }
  1694. else if (std::strcmp(msg, "set_panning") == 0)
  1695. {
  1696. uint32_t pluginId;
  1697. float value;
  1698. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1699. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  1700. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1701. plugin->setPanning(value, true, false);
  1702. }
  1703. else if (std::strcmp(msg, "set_ctrl_channel") == 0)
  1704. {
  1705. uint32_t pluginId;
  1706. int32_t channel;
  1707. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1708. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(channel), true);
  1709. CARLA_SAFE_ASSERT_RETURN(channel >= -1 && channel < MAX_MIDI_CHANNELS, true);
  1710. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1711. plugin->setCtrlChannel(int8_t(channel), true, false);
  1712. }
  1713. else if (std::strcmp(msg, "set_parameter_value") == 0)
  1714. {
  1715. uint32_t pluginId, parameterId;
  1716. float value;
  1717. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1718. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
  1719. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  1720. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1721. {
  1722. plugin->setParameterValue(parameterId, value, true, true, false);
  1723. fEngine->setParameterValueFromUI(pluginId, parameterId, value);
  1724. }
  1725. }
  1726. else if (std::strcmp(msg, "set_parameter_midi_channel") == 0)
  1727. {
  1728. uint32_t pluginId, parameterId, channel;
  1729. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1730. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
  1731. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(channel), true);
  1732. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, true);
  1733. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1734. plugin->setParameterMidiChannel(parameterId, static_cast<uint8_t>(channel), true, false);
  1735. }
  1736. else if (std::strcmp(msg, "set_parameter_mapped_control_index") == 0)
  1737. {
  1738. uint32_t pluginId, parameterId;
  1739. int32_t ctrl;
  1740. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1741. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
  1742. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(ctrl), true);
  1743. CARLA_SAFE_ASSERT_RETURN(ctrl >= CONTROL_INDEX_NONE && ctrl <= CONTROL_INDEX_MAX_ALLOWED, true);
  1744. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1745. plugin->setParameterMappedControlIndex(parameterId, static_cast<int16_t>(ctrl), true, false);
  1746. }
  1747. else if (std::strcmp(msg, "set_parameter_mapped_range") == 0)
  1748. {
  1749. uint32_t pluginId, parameterId;
  1750. float minimum, maximum;
  1751. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1752. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
  1753. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(minimum), true);
  1754. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(maximum), true);
  1755. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1756. plugin->setParameterMappedRange(parameterId, minimum, maximum, true, false);
  1757. }
  1758. else if (std::strcmp(msg, "set_parameter_touch") == 0)
  1759. {
  1760. uint32_t pluginId, parameterId;
  1761. bool touching;
  1762. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1763. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
  1764. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(touching), true);
  1765. if (fEngine->getPlugin(pluginId))
  1766. fEngine->setParameterTouchFromUI(pluginId, parameterId, touching);
  1767. }
  1768. else if (std::strcmp(msg, "set_program") == 0)
  1769. {
  1770. uint32_t pluginId;
  1771. int32_t index;
  1772. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1773. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index), true);
  1774. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1775. {
  1776. plugin->setProgram(index, true, true, false);
  1777. _updateParamValues(plugin, pluginId, true, true);
  1778. }
  1779. }
  1780. else if (std::strcmp(msg, "set_midi_program") == 0)
  1781. {
  1782. uint32_t pluginId;
  1783. int32_t index;
  1784. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1785. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index), true);
  1786. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1787. {
  1788. plugin->setMidiProgram(index, true, true, false);
  1789. _updateParamValues(plugin, pluginId, true, true);
  1790. }
  1791. }
  1792. else if (std::strcmp(msg, "set_custom_data") == 0)
  1793. {
  1794. uint32_t pluginId;
  1795. const char* type;
  1796. const char* key;
  1797. const char* value;
  1798. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1799. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(type, true), true);
  1800. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(key, true), true);
  1801. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(value, false), true);
  1802. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1803. plugin->setCustomData(type, key, value, true);
  1804. delete[] type;
  1805. delete[] key;
  1806. }
  1807. else if (std::strcmp(msg, "set_chunk_data") == 0)
  1808. {
  1809. uint32_t pluginId;
  1810. const char* cdata;
  1811. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1812. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(cdata, false), true);
  1813. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1814. {
  1815. std::vector<uint8_t> chunk(carla_getChunkFromBase64String(cdata));
  1816. #ifdef CARLA_PROPER_CPP11_SUPPORT
  1817. plugin->setChunkData(chunk.data(), chunk.size());
  1818. #else
  1819. plugin->setChunkData(&chunk.front(), chunk.size());
  1820. #endif
  1821. _updateParamValues(plugin, pluginId, false, true);
  1822. }
  1823. }
  1824. else if (std::strcmp(msg, "prepare_for_save") == 0)
  1825. {
  1826. uint32_t pluginId;
  1827. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1828. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1829. plugin->prepareForSave();
  1830. }
  1831. else if (std::strcmp(msg, "reset_parameters") == 0)
  1832. {
  1833. uint32_t pluginId;
  1834. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1835. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1836. {
  1837. plugin->resetParameters();
  1838. _updateParamValues(plugin, pluginId, false, true);
  1839. }
  1840. }
  1841. else if (std::strcmp(msg, "randomize_parameters") == 0)
  1842. {
  1843. uint32_t pluginId;
  1844. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1845. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1846. {
  1847. plugin->randomizeParameters();
  1848. _updateParamValues(plugin, pluginId, false, true);
  1849. }
  1850. }
  1851. else if (std::strcmp(msg, "send_midi_note") == 0)
  1852. {
  1853. uint32_t pluginId, channel, note, velocity;
  1854. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1855. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(channel), true);
  1856. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(note), true);
  1857. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(velocity), true);
  1858. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, true);
  1859. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_VALUE, true);
  1860. CARLA_SAFE_ASSERT_RETURN(velocity < MAX_MIDI_VALUE, true);
  1861. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1862. plugin->sendMidiSingleNote(static_cast<uint8_t>(channel), static_cast<uint8_t>(note), static_cast<uint8_t>(velocity), true, true, false);
  1863. }
  1864. else if (std::strcmp(msg, "show_custom_ui") == 0)
  1865. {
  1866. uint32_t pluginId;
  1867. bool yesNo;
  1868. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  1869. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo), true);
  1870. if (const CarlaPluginPtr plugin = fEngine->getPlugin(pluginId))
  1871. plugin->showCustomUI(yesNo);
  1872. }
  1873. else
  1874. {
  1875. carla_stderr("CarlaEngineNativeUI::msgReceived : %s", msg);
  1876. return false;
  1877. }
  1878. if (! ok)
  1879. {
  1880. const CarlaMutexLocker cml(getPipeLock());
  1881. if (writeMessage("error\n", 6) && writeAndFixMessage(fEngine->getLastError()))
  1882. flushMessages();
  1883. }
  1884. return true;
  1885. }
  1886. void CarlaEngineNativeUI::_updateParamValues(const CarlaPluginPtr& plugin,
  1887. const uint32_t pluginId,
  1888. const bool sendCallback, const bool sendPluginHost) const noexcept
  1889. {
  1890. float value;
  1891. for (uint32_t i=0, count=plugin->getParameterCount(); i<count; ++i) {
  1892. value = plugin->getParameterValue(i);
  1893. if (sendCallback) {
  1894. fEngine->callback(true, true,
  1895. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1896. pluginId,
  1897. static_cast<int>(i),
  1898. 0, 0,
  1899. value,
  1900. nullptr);
  1901. }
  1902. if (sendPluginHost) {
  1903. carla_stdout("_updateParamValues");
  1904. fEngine->setParameterValueFromUI(pluginId, i, value);
  1905. }
  1906. }
  1907. }
  1908. // -----------------------------------------------------------------------
  1909. static const NativePluginDescriptor carlaRackDesc = {
  1910. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  1911. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  1912. |NATIVE_PLUGIN_HAS_UI
  1913. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  1914. |NATIVE_PLUGIN_USES_STATE
  1915. |NATIVE_PLUGIN_USES_TIME
  1916. |NATIVE_PLUGIN_USES_UI_SIZE),
  1917. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  1918. /* audioIns */ 2,
  1919. /* audioOuts */ 2,
  1920. /* midiIns */ 1,
  1921. /* midiOuts */ 1,
  1922. /* paramIns */ kNumInParams,
  1923. /* paramOuts */ kNumOutParams,
  1924. /* name */ "Carla-Rack",
  1925. /* label */ "carlarack",
  1926. /* maker */ "falkTX",
  1927. /* copyright */ "GNU GPL v2+",
  1928. CarlaEngineNative::_instantiateRack,
  1929. CarlaEngineNative::_cleanup,
  1930. CarlaEngineNative::_get_parameter_count,
  1931. CarlaEngineNative::_get_parameter_info,
  1932. CarlaEngineNative::_get_parameter_value,
  1933. /* _get_midi_program_count */ nullptr,
  1934. /* _get_midi_program_info */ nullptr,
  1935. CarlaEngineNative::_set_parameter_value,
  1936. /* _set_midi_program */ nullptr,
  1937. /* _set_custom_data */ nullptr,
  1938. CarlaEngineNative::_ui_show,
  1939. CarlaEngineNative::_ui_idle,
  1940. CarlaEngineNative::_ui_set_parameter_value,
  1941. /* _ui_set_midi_program */ nullptr,
  1942. /* _ui_set_custom_data */ nullptr,
  1943. CarlaEngineNative::_activate,
  1944. CarlaEngineNative::_deactivate,
  1945. CarlaEngineNative::_process,
  1946. CarlaEngineNative::_get_state,
  1947. CarlaEngineNative::_set_state,
  1948. CarlaEngineNative::_dispatcher,
  1949. /* _render_inline_dsplay */ nullptr,
  1950. /* cvIns */ 0,
  1951. /* cvOuts */ 0,
  1952. /* _get_buffer_port_name */ nullptr,
  1953. /* _get_buffer_port_range */ nullptr,
  1954. /* ui_width */ kUiWidth,
  1955. /* ui_height */ kUiHeight
  1956. };
  1957. static const NativePluginDescriptor carlaRackNoMidiOutDesc = {
  1958. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  1959. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  1960. |NATIVE_PLUGIN_HAS_UI
  1961. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  1962. |NATIVE_PLUGIN_USES_STATE
  1963. |NATIVE_PLUGIN_USES_TIME
  1964. |NATIVE_PLUGIN_USES_UI_SIZE),
  1965. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  1966. /* audioIns */ 2,
  1967. /* audioOuts */ 2,
  1968. /* midiIns */ 1,
  1969. /* midiOuts */ 0,
  1970. /* paramIns */ kNumInParams,
  1971. /* paramOuts */ kNumOutParams,
  1972. /* name */ "Carla-Rack (no midi out)",
  1973. /* label */ "carlarack-nomidiout",
  1974. /* maker */ "falkTX",
  1975. /* copyright */ "GNU GPL v2+",
  1976. CarlaEngineNative::_instantiateRackNoMidiOut,
  1977. CarlaEngineNative::_cleanup,
  1978. CarlaEngineNative::_get_parameter_count,
  1979. CarlaEngineNative::_get_parameter_info,
  1980. CarlaEngineNative::_get_parameter_value,
  1981. /* _get_midi_program_count */ nullptr,
  1982. /* _get_midi_program_info */ nullptr,
  1983. CarlaEngineNative::_set_parameter_value,
  1984. /* _set_midi_program */ nullptr,
  1985. /* _set_custom_data */ nullptr,
  1986. CarlaEngineNative::_ui_show,
  1987. CarlaEngineNative::_ui_idle,
  1988. CarlaEngineNative::_ui_set_parameter_value,
  1989. /* _ui_set_midi_program */ nullptr,
  1990. /* _ui_set_custom_data */ nullptr,
  1991. CarlaEngineNative::_activate,
  1992. CarlaEngineNative::_deactivate,
  1993. CarlaEngineNative::_process,
  1994. CarlaEngineNative::_get_state,
  1995. CarlaEngineNative::_set_state,
  1996. CarlaEngineNative::_dispatcher,
  1997. /* _render_inline_dsplay */ nullptr,
  1998. /* cvIns */ 0,
  1999. /* cvOuts */ 0,
  2000. /* _get_buffer_port_name */ nullptr,
  2001. /* _get_buffer_port_range */ nullptr,
  2002. /* ui_width */ kUiWidth,
  2003. /* ui_height */ kUiHeight
  2004. };
  2005. static const NativePluginDescriptor carlaPatchbayDesc = {
  2006. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  2007. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  2008. |NATIVE_PLUGIN_HAS_UI
  2009. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  2010. |NATIVE_PLUGIN_USES_STATE
  2011. |NATIVE_PLUGIN_USES_TIME
  2012. |NATIVE_PLUGIN_USES_UI_SIZE),
  2013. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  2014. /* audioIns */ 2,
  2015. /* audioOuts */ 2,
  2016. /* midiIns */ 1,
  2017. /* midiOuts */ 1,
  2018. /* paramIns */ kNumInParams,
  2019. /* paramOuts */ kNumOutParams,
  2020. /* name */ "Carla-Patchbay",
  2021. /* label */ "carlapatchbay",
  2022. /* maker */ "falkTX",
  2023. /* copyright */ "GNU GPL v2+",
  2024. CarlaEngineNative::_instantiatePatchbay,
  2025. CarlaEngineNative::_cleanup,
  2026. CarlaEngineNative::_get_parameter_count,
  2027. CarlaEngineNative::_get_parameter_info,
  2028. CarlaEngineNative::_get_parameter_value,
  2029. /* _get_midi_program_count */ nullptr,
  2030. /* _get_midi_program_info */ nullptr,
  2031. CarlaEngineNative::_set_parameter_value,
  2032. /* _set_midi_program */ nullptr,
  2033. /* _set_custom_data */ nullptr,
  2034. CarlaEngineNative::_ui_show,
  2035. CarlaEngineNative::_ui_idle,
  2036. CarlaEngineNative::_ui_set_parameter_value,
  2037. /* _ui_set_midi_program */ nullptr,
  2038. /* _ui_set_custom_data */ nullptr,
  2039. CarlaEngineNative::_activate,
  2040. CarlaEngineNative::_deactivate,
  2041. CarlaEngineNative::_process,
  2042. CarlaEngineNative::_get_state,
  2043. CarlaEngineNative::_set_state,
  2044. CarlaEngineNative::_dispatcher,
  2045. /* _render_inline_dsplay */ nullptr,
  2046. /* cvIns */ 0,
  2047. /* cvOuts */ 0,
  2048. /* _get_buffer_port_name */ nullptr,
  2049. /* _get_buffer_port_range */ nullptr,
  2050. /* ui_width */ kUiWidth,
  2051. /* ui_height */ kUiHeight
  2052. };
  2053. static const NativePluginDescriptor carlaPatchbay3sDesc = {
  2054. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  2055. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  2056. |NATIVE_PLUGIN_HAS_UI
  2057. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  2058. |NATIVE_PLUGIN_USES_STATE
  2059. |NATIVE_PLUGIN_USES_TIME
  2060. |NATIVE_PLUGIN_USES_UI_SIZE),
  2061. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  2062. /* audioIns */ 3,
  2063. /* audioOuts */ 2,
  2064. /* midiIns */ 1,
  2065. /* midiOuts */ 1,
  2066. /* paramIns */ kNumInParams,
  2067. /* paramOuts */ kNumOutParams,
  2068. /* name */ "Carla-Patchbay (sidechain)",
  2069. /* label */ "carlapatchbay3s",
  2070. /* maker */ "falkTX",
  2071. /* copyright */ "GNU GPL v2+",
  2072. CarlaEngineNative::_instantiatePatchbay3s,
  2073. CarlaEngineNative::_cleanup,
  2074. CarlaEngineNative::_get_parameter_count,
  2075. CarlaEngineNative::_get_parameter_info,
  2076. CarlaEngineNative::_get_parameter_value,
  2077. /* _get_midi_program_count */ nullptr,
  2078. /* _get_midi_program_info */ nullptr,
  2079. CarlaEngineNative::_set_parameter_value,
  2080. /* _set_midi_program */ nullptr,
  2081. /* _set_custom_data */ nullptr,
  2082. CarlaEngineNative::_ui_show,
  2083. CarlaEngineNative::_ui_idle,
  2084. CarlaEngineNative::_ui_set_parameter_value,
  2085. /* _ui_set_midi_program */ nullptr,
  2086. /* _ui_set_custom_data */ nullptr,
  2087. CarlaEngineNative::_activate,
  2088. CarlaEngineNative::_deactivate,
  2089. CarlaEngineNative::_process,
  2090. CarlaEngineNative::_get_state,
  2091. CarlaEngineNative::_set_state,
  2092. CarlaEngineNative::_dispatcher,
  2093. /* _render_inline_dsplay */ nullptr,
  2094. /* cvIns */ 0,
  2095. /* cvOuts */ 0,
  2096. /* _get_buffer_port_name */ nullptr,
  2097. /* _get_buffer_port_range */ nullptr,
  2098. /* ui_width */ kUiWidth,
  2099. /* ui_height */ kUiHeight
  2100. };
  2101. static const NativePluginDescriptor carlaPatchbay16Desc = {
  2102. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  2103. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  2104. |NATIVE_PLUGIN_HAS_UI
  2105. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  2106. |NATIVE_PLUGIN_USES_STATE
  2107. |NATIVE_PLUGIN_USES_TIME
  2108. |NATIVE_PLUGIN_USES_UI_SIZE),
  2109. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  2110. /* audioIns */ 16,
  2111. /* audioOuts */ 16,
  2112. /* midiIns */ 1,
  2113. /* midiOuts */ 1,
  2114. /* paramIns */ kNumInParams,
  2115. /* paramOuts */ kNumOutParams,
  2116. /* name */ "Carla-Patchbay (16chan)",
  2117. /* label */ "carlapatchbay16",
  2118. /* maker */ "falkTX",
  2119. /* copyright */ "GNU GPL v2+",
  2120. CarlaEngineNative::_instantiatePatchbay16,
  2121. CarlaEngineNative::_cleanup,
  2122. CarlaEngineNative::_get_parameter_count,
  2123. CarlaEngineNative::_get_parameter_info,
  2124. CarlaEngineNative::_get_parameter_value,
  2125. /* _get_midi_program_count */ nullptr,
  2126. /* _get_midi_program_info */ nullptr,
  2127. CarlaEngineNative::_set_parameter_value,
  2128. /* _set_midi_program */ nullptr,
  2129. /* _set_custom_data */ nullptr,
  2130. CarlaEngineNative::_ui_show,
  2131. CarlaEngineNative::_ui_idle,
  2132. CarlaEngineNative::_ui_set_parameter_value,
  2133. /* _ui_set_midi_program */ nullptr,
  2134. /* _ui_set_custom_data */ nullptr,
  2135. CarlaEngineNative::_activate,
  2136. CarlaEngineNative::_deactivate,
  2137. CarlaEngineNative::_process,
  2138. CarlaEngineNative::_get_state,
  2139. CarlaEngineNative::_set_state,
  2140. CarlaEngineNative::_dispatcher,
  2141. /* _render_inline_dsplay */ nullptr,
  2142. /* cvIns */ 0,
  2143. /* cvOuts */ 0,
  2144. /* _get_buffer_port_name */ nullptr,
  2145. /* _get_buffer_port_range */ nullptr,
  2146. /* ui_width */ kUiWidth,
  2147. /* ui_height */ kUiHeight
  2148. };
  2149. static const NativePluginDescriptor carlaPatchbay32Desc = {
  2150. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  2151. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  2152. |NATIVE_PLUGIN_HAS_UI
  2153. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  2154. |NATIVE_PLUGIN_USES_STATE
  2155. |NATIVE_PLUGIN_USES_TIME
  2156. |NATIVE_PLUGIN_USES_UI_SIZE),
  2157. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  2158. /* audioIns */ 32,
  2159. /* audioOuts */ 32,
  2160. /* midiIns */ 1,
  2161. /* midiOuts */ 1,
  2162. /* paramIns */ kNumInParams,
  2163. /* paramOuts */ kNumOutParams,
  2164. /* name */ "Carla-Patchbay (32chan)",
  2165. /* label */ "carlapatchbay32",
  2166. /* maker */ "falkTX",
  2167. /* copyright */ "GNU GPL v2+",
  2168. CarlaEngineNative::_instantiatePatchbay32,
  2169. CarlaEngineNative::_cleanup,
  2170. CarlaEngineNative::_get_parameter_count,
  2171. CarlaEngineNative::_get_parameter_info,
  2172. CarlaEngineNative::_get_parameter_value,
  2173. /* _get_midi_program_count */ nullptr,
  2174. /* _get_midi_program_info */ nullptr,
  2175. CarlaEngineNative::_set_parameter_value,
  2176. /* _set_midi_program */ nullptr,
  2177. /* _set_custom_data */ nullptr,
  2178. CarlaEngineNative::_ui_show,
  2179. CarlaEngineNative::_ui_idle,
  2180. CarlaEngineNative::_ui_set_parameter_value,
  2181. /* _ui_set_midi_program */ nullptr,
  2182. /* _ui_set_custom_data */ nullptr,
  2183. CarlaEngineNative::_activate,
  2184. CarlaEngineNative::_deactivate,
  2185. CarlaEngineNative::_process,
  2186. CarlaEngineNative::_get_state,
  2187. CarlaEngineNative::_set_state,
  2188. CarlaEngineNative::_dispatcher,
  2189. /* _render_inline_dsplay */ nullptr,
  2190. /* cvIns */ 0,
  2191. /* cvOuts */ 0,
  2192. /* _get_buffer_port_name */ nullptr,
  2193. /* _get_buffer_port_range */ nullptr,
  2194. /* ui_width */ kUiWidth,
  2195. /* ui_height */ kUiHeight
  2196. };
  2197. static const NativePluginDescriptor carlaPatchbay64Desc = {
  2198. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  2199. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  2200. |NATIVE_PLUGIN_HAS_UI
  2201. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  2202. |NATIVE_PLUGIN_USES_STATE
  2203. |NATIVE_PLUGIN_USES_TIME
  2204. |NATIVE_PLUGIN_USES_UI_SIZE),
  2205. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  2206. /* audioIns */ 64,
  2207. /* audioOuts */ 64,
  2208. /* midiIns */ 1,
  2209. /* midiOuts */ 1,
  2210. /* paramIns */ kNumInParams,
  2211. /* paramOuts */ kNumOutParams,
  2212. /* name */ "Carla-Patchbay (64chan)",
  2213. /* label */ "carlapatchbay64",
  2214. /* maker */ "falkTX",
  2215. /* copyright */ "GNU GPL v2+",
  2216. CarlaEngineNative::_instantiatePatchbay64,
  2217. CarlaEngineNative::_cleanup,
  2218. CarlaEngineNative::_get_parameter_count,
  2219. CarlaEngineNative::_get_parameter_info,
  2220. CarlaEngineNative::_get_parameter_value,
  2221. /* _get_midi_program_count */ nullptr,
  2222. /* _get_midi_program_info */ nullptr,
  2223. CarlaEngineNative::_set_parameter_value,
  2224. /* _set_midi_program */ nullptr,
  2225. /* _set_custom_data */ nullptr,
  2226. CarlaEngineNative::_ui_show,
  2227. CarlaEngineNative::_ui_idle,
  2228. CarlaEngineNative::_ui_set_parameter_value,
  2229. /* _ui_set_midi_program */ nullptr,
  2230. /* _ui_set_custom_data */ nullptr,
  2231. CarlaEngineNative::_activate,
  2232. CarlaEngineNative::_deactivate,
  2233. CarlaEngineNative::_process,
  2234. CarlaEngineNative::_get_state,
  2235. CarlaEngineNative::_set_state,
  2236. CarlaEngineNative::_dispatcher,
  2237. /* _render_inline_dsplay */ nullptr,
  2238. /* cvIns */ 0,
  2239. /* cvOuts */ 0,
  2240. /* _get_buffer_port_name */ nullptr,
  2241. /* _get_buffer_port_range */ nullptr,
  2242. /* ui_width */ kUiWidth,
  2243. /* ui_height */ kUiHeight
  2244. };
  2245. static const NativePluginDescriptor carlaPatchbayCVDesc = {
  2246. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  2247. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  2248. |NATIVE_PLUGIN_HAS_UI
  2249. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  2250. |NATIVE_PLUGIN_USES_CONTROL_VOLTAGE
  2251. |NATIVE_PLUGIN_USES_STATE
  2252. |NATIVE_PLUGIN_USES_TIME
  2253. |NATIVE_PLUGIN_USES_UI_SIZE),
  2254. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  2255. /* audioIns */ 2,
  2256. /* audioOuts */ 2,
  2257. /* midiIns */ 1,
  2258. /* midiOuts */ 1,
  2259. /* paramIns */ kNumInParams,
  2260. /* paramOuts */ kNumOutParams,
  2261. /* name */ "Carla-Patchbay (CV)",
  2262. /* label */ "carlapatchbaycv",
  2263. /* maker */ "falkTX",
  2264. /* copyright */ "GNU GPL v2+",
  2265. CarlaEngineNative::_instantiatePatchbayCV,
  2266. CarlaEngineNative::_cleanup,
  2267. CarlaEngineNative::_get_parameter_count,
  2268. CarlaEngineNative::_get_parameter_info,
  2269. CarlaEngineNative::_get_parameter_value,
  2270. /* _get_midi_program_count */ nullptr,
  2271. /* _get_midi_program_info */ nullptr,
  2272. CarlaEngineNative::_set_parameter_value,
  2273. /* _set_midi_program */ nullptr,
  2274. /* _set_custom_data */ nullptr,
  2275. CarlaEngineNative::_ui_show,
  2276. CarlaEngineNative::_ui_idle,
  2277. CarlaEngineNative::_ui_set_parameter_value,
  2278. /* _ui_set_midi_program */ nullptr,
  2279. /* _ui_set_custom_data */ nullptr,
  2280. CarlaEngineNative::_activate,
  2281. CarlaEngineNative::_deactivate,
  2282. CarlaEngineNative::_process,
  2283. CarlaEngineNative::_get_state,
  2284. CarlaEngineNative::_set_state,
  2285. CarlaEngineNative::_dispatcher,
  2286. /* _render_inline_dsplay */ nullptr,
  2287. /* cvIns */ 5,
  2288. /* cvOuts */ 5,
  2289. /* _get_buffer_port_name */ nullptr,
  2290. /* _get_buffer_port_range */ nullptr,
  2291. /* ui_width */ kUiWidth,
  2292. /* ui_height */ kUiHeight
  2293. };
  2294. CARLA_BACKEND_END_NAMESPACE
  2295. // -----------------------------------------------------------------------
  2296. CARLA_EXPORT
  2297. void carla_register_native_plugin_carla();
  2298. void carla_register_native_plugin_carla()
  2299. {
  2300. CARLA_BACKEND_USE_NAMESPACE;
  2301. carla_register_native_plugin(&carlaRackDesc);
  2302. carla_register_native_plugin(&carlaRackNoMidiOutDesc);
  2303. carla_register_native_plugin(&carlaPatchbayDesc);
  2304. carla_register_native_plugin(&carlaPatchbay3sDesc);
  2305. carla_register_native_plugin(&carlaPatchbay16Desc);
  2306. carla_register_native_plugin(&carlaPatchbay32Desc);
  2307. carla_register_native_plugin(&carlaPatchbay64Desc);
  2308. carla_register_native_plugin(&carlaPatchbayCVDesc);
  2309. }
  2310. // -----------------------------------------------------------------------
  2311. const NativePluginDescriptor* carla_get_native_rack_plugin()
  2312. {
  2313. CARLA_BACKEND_USE_NAMESPACE;
  2314. return &carlaRackDesc;
  2315. }
  2316. const NativePluginDescriptor* carla_get_native_patchbay_plugin()
  2317. {
  2318. CARLA_BACKEND_USE_NAMESPACE;
  2319. return &carlaPatchbayDesc;
  2320. }
  2321. const NativePluginDescriptor* carla_get_native_patchbay16_plugin()
  2322. {
  2323. CARLA_BACKEND_USE_NAMESPACE;
  2324. return &carlaPatchbay16Desc;
  2325. }
  2326. const NativePluginDescriptor* carla_get_native_patchbay32_plugin()
  2327. {
  2328. CARLA_BACKEND_USE_NAMESPACE;
  2329. return &carlaPatchbay32Desc;
  2330. }
  2331. const NativePluginDescriptor* carla_get_native_patchbay64_plugin()
  2332. {
  2333. CARLA_BACKEND_USE_NAMESPACE;
  2334. return &carlaPatchbay64Desc;
  2335. }
  2336. const NativePluginDescriptor* carla_get_native_patchbay_cv_plugin()
  2337. {
  2338. CARLA_BACKEND_USE_NAMESPACE;
  2339. return &carlaPatchbayCVDesc;
  2340. }
  2341. // -----------------------------------------------------------------------
  2342. // Extra stuff for linking purposes
  2343. #ifdef CARLA_PLUGIN_EXPORT
  2344. CARLA_BACKEND_START_NAMESPACE
  2345. namespace EngineInit {
  2346. CarlaEngine* newJack() { return nullptr; }
  2347. #ifdef USING_JUCE_AUDIO_DEVICES
  2348. CarlaEngine* newJuce(const AudioApi) { return nullptr; }
  2349. uint getJuceApiCount() { return 0; }
  2350. const char* getJuceApiName(const uint) { return nullptr; }
  2351. const char* const* getJuceApiDeviceNames(const uint) { return nullptr; }
  2352. const EngineDriverDeviceInfo* getJuceDeviceInfo(const uint, const char* const) { return nullptr; }
  2353. bool showJuceDeviceControlPanel(const uint, const char* const) { return false; }
  2354. #else
  2355. CarlaEngine* newRtAudio(const AudioApi) { return nullptr; }
  2356. uint getRtAudioApiCount() { return 0; }
  2357. const char* getRtAudioApiName(const uint) { return nullptr; }
  2358. const char* const* getRtAudioApiDeviceNames(const uint) { return nullptr; }
  2359. const EngineDriverDeviceInfo* getRtAudioDeviceInfo(const uint, const char* const) { return nullptr; }
  2360. #endif
  2361. }
  2362. CARLA_BACKEND_END_NAMESPACE
  2363. #define CARLA_PLUGIN_UI_CLASS_PREFIX EngineNative
  2364. #include "CarlaHostCommon.cpp"
  2365. #include "CarlaPluginUI.cpp"
  2366. #include "CarlaDssiUtils.cpp"
  2367. #include "CarlaMacUtils.cpp"
  2368. #include "CarlaPatchbayUtils.cpp"
  2369. #include "CarlaPipeUtils.cpp"
  2370. #include "CarlaProcessUtils.cpp"
  2371. #include "CarlaStateUtils.cpp"
  2372. #endif
  2373. // -----------------------------------------------------------------------