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

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