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

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
6 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
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333
  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaDefines.h"
  18. #ifdef BUILD_BRIDGE
  19. # error This file should not be compiled if building bridge
  20. #endif
  21. #include "CarlaEngineInternal.hpp"
  22. #include "CarlaPlugin.hpp"
  23. #include "CarlaBackendUtils.hpp"
  24. #include "CarlaBase64Utils.hpp"
  25. #include "CarlaBinaryUtils.hpp"
  26. #include "CarlaMathUtils.hpp"
  27. #include "CarlaStateUtils.hpp"
  28. #include "CarlaExternalUI.hpp"
  29. #include "CarlaHost.h"
  30. #include "CarlaNative.hpp"
  31. #include "water/files/File.h"
  32. #include "water/streams/MemoryOutputStream.h"
  33. #include "water/xml/XmlDocument.h"
  34. #include "water/xml/XmlElement.h"
  35. using water::File;
  36. using water::MemoryOutputStream;
  37. using water::String;
  38. using water::XmlDocument;
  39. using water::XmlElement;
  40. CARLA_BACKEND_START_NAMESPACE
  41. // -----------------------------------------------------------------------
  42. class CarlaEngineNativeUI : public CarlaExternalUI
  43. {
  44. public:
  45. CarlaEngineNativeUI(CarlaEngine* const engine)
  46. : fEngine(engine),
  47. fRemoteWinId(0)
  48. {
  49. carla_debug("CarlaEngineNativeUI::CarlaEngineNativeUI(%p)", engine);
  50. }
  51. ~CarlaEngineNativeUI() noexcept override
  52. {
  53. carla_debug("CarlaEngineNativeUI::~CarlaEngineNativeUI()");
  54. }
  55. bool isReady() const noexcept
  56. {
  57. return fRemoteWinId != 0;
  58. }
  59. intptr_t getRemoteWinId() const noexcept
  60. {
  61. return fRemoteWinId;
  62. }
  63. protected:
  64. bool msgReceived(const char* const msg) noexcept override
  65. {
  66. if (CarlaExternalUI::msgReceived(msg))
  67. return true;
  68. bool ok = true;
  69. if (std::strcmp(msg, "set_engine_option") == 0)
  70. {
  71. uint32_t option;
  72. int32_t value;
  73. const char* valueStr = nullptr;
  74. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(option), true);
  75. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(value), true);
  76. readNextLineAsString(valueStr); // can be null
  77. try {
  78. fEngine->setOption(static_cast<EngineOption>(option), value, valueStr);
  79. } CARLA_SAFE_EXCEPTION("setOption");
  80. if (valueStr != nullptr)
  81. delete[] valueStr;
  82. }
  83. else if (std::strcmp(msg, "load_file") == 0)
  84. {
  85. const char* filename;
  86. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename), true);
  87. try {
  88. ok = fEngine->loadFile(filename);
  89. } CARLA_SAFE_EXCEPTION("loadFile");
  90. delete[] filename;
  91. }
  92. else if (std::strcmp(msg, "load_project") == 0)
  93. {
  94. const char* filename;
  95. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename), true);
  96. try {
  97. ok = fEngine->loadProject(filename);
  98. } CARLA_SAFE_EXCEPTION("loadProject");
  99. delete[] filename;
  100. }
  101. else if (std::strcmp(msg, "save_project") == 0)
  102. {
  103. const char* filename;
  104. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename), true);
  105. try {
  106. ok = fEngine->saveProject(filename);
  107. } CARLA_SAFE_EXCEPTION("saveProject");
  108. delete[] filename;
  109. }
  110. else if (std::strcmp(msg, "patchbay_connect") == 0)
  111. {
  112. uint32_t groupA, portA, groupB, portB;
  113. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(groupA), true);
  114. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(portA), true);
  115. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(groupB), true);
  116. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(portB), true);
  117. try {
  118. ok = fEngine->patchbayConnect(groupA, portA, groupB, portB);
  119. } CARLA_SAFE_EXCEPTION("patchbayConnect");
  120. }
  121. else if (std::strcmp(msg, "patchbay_disconnect") == 0)
  122. {
  123. uint32_t connectionId;
  124. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(connectionId), true);
  125. try {
  126. ok = fEngine->patchbayDisconnect(connectionId);
  127. } CARLA_SAFE_EXCEPTION("patchbayDisconnect");
  128. }
  129. else if (std::strcmp(msg, "patchbay_refresh") == 0)
  130. {
  131. try {
  132. ok = fEngine->patchbayRefresh(false);
  133. } CARLA_SAFE_EXCEPTION("patchbayRefresh");
  134. }
  135. else if (std::strcmp(msg, "transport_play") == 0)
  136. {
  137. fEngine->transportPlay();
  138. }
  139. else if (std::strcmp(msg, "transport_pause") == 0)
  140. {
  141. fEngine->transportPause();
  142. }
  143. else if (std::strcmp(msg, "transport_bpm") == 0)
  144. {
  145. double bpm;
  146. CARLA_SAFE_ASSERT_RETURN(readNextLineAsDouble(bpm), true);
  147. fEngine->transportBPM(bpm);
  148. }
  149. else if (std::strcmp(msg, "transport_relocate") == 0)
  150. {
  151. uint64_t frame;
  152. CARLA_SAFE_ASSERT_RETURN(readNextLineAsULong(frame), true);
  153. fEngine->transportRelocate(frame);
  154. }
  155. else if (std::strcmp(msg, "add_plugin") == 0)
  156. {
  157. uint32_t btype, ptype;
  158. const char* filename = nullptr;
  159. const char* name;
  160. const char* label;
  161. int64_t uniqueId;
  162. uint options;
  163. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(btype), true);
  164. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(ptype), true);
  165. readNextLineAsString(filename); // can be null
  166. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(name), true);
  167. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(label), true);
  168. CARLA_SAFE_ASSERT_RETURN(readNextLineAsLong(uniqueId), true);
  169. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(options), true);
  170. if (filename != nullptr && std::strcmp(filename, "(null)") == 0)
  171. {
  172. delete[] filename;
  173. filename = nullptr;
  174. }
  175. if (std::strcmp(name, "(null)") == 0)
  176. {
  177. delete[] name;
  178. name = nullptr;
  179. }
  180. ok = fEngine->addPlugin(static_cast<BinaryType>(btype), static_cast<PluginType>(ptype),
  181. filename, name, label, uniqueId, nullptr, options);
  182. if (filename != nullptr)
  183. delete[] filename;
  184. if (name != nullptr)
  185. delete[] name;
  186. delete[] label;
  187. }
  188. else if (std::strcmp(msg, "remove_plugin") == 0)
  189. {
  190. uint32_t pluginId;
  191. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  192. ok = fEngine->removePlugin(pluginId);
  193. }
  194. else if (std::strcmp(msg, "remove_all_plugins") == 0)
  195. {
  196. ok = fEngine->removeAllPlugins();
  197. }
  198. else if (std::strcmp(msg, "rename_plugin") == 0)
  199. {
  200. uint32_t pluginId;
  201. const char* newName;
  202. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  203. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(newName), true);
  204. // TODO
  205. /*const char* name =*/ fEngine->renamePlugin(pluginId, newName);
  206. delete[] newName;
  207. }
  208. else if (std::strcmp(msg, "clone_plugin") == 0)
  209. {
  210. uint32_t pluginId;
  211. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  212. ok = fEngine->clonePlugin(pluginId);
  213. }
  214. else if (std::strcmp(msg, "replace_plugin") == 0)
  215. {
  216. uint32_t pluginId;
  217. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  218. ok = fEngine->replacePlugin(pluginId);
  219. }
  220. else if (std::strcmp(msg, "switch_plugins") == 0)
  221. {
  222. uint32_t pluginIdA, pluginIdB;
  223. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginIdA), true);
  224. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginIdB), true);
  225. ok = fEngine->switchPlugins(pluginIdA, pluginIdB);
  226. }
  227. else if (std::strcmp(msg, "load_plugin_state") == 0)
  228. {
  229. uint32_t pluginId;
  230. const char* filename;
  231. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  232. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename), true);
  233. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  234. plugin->loadStateFromFile(filename);
  235. delete[] filename;
  236. }
  237. else if (std::strcmp(msg, "save_plugin_state") == 0)
  238. {
  239. uint32_t pluginId;
  240. const char* filename;
  241. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  242. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename), true);
  243. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  244. plugin->saveStateToFile(filename);
  245. delete[] filename;
  246. }
  247. else if (std::strcmp(msg, "set_option") == 0)
  248. {
  249. uint32_t pluginId, option;
  250. bool yesNo;
  251. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  252. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(option), true);
  253. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo), true);
  254. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  255. plugin->setOption(option, yesNo, false);
  256. }
  257. else if (std::strcmp(msg, "set_active") == 0)
  258. {
  259. uint32_t pluginId;
  260. bool onOff;
  261. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  262. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(onOff), true);
  263. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  264. plugin->setActive(onOff, true, false);
  265. }
  266. else if (std::strcmp(msg, "set_drywet") == 0)
  267. {
  268. uint32_t pluginId;
  269. float value;
  270. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  271. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  272. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  273. plugin->setDryWet(value, true, false);
  274. }
  275. else if (std::strcmp(msg, "set_volume") == 0)
  276. {
  277. uint32_t pluginId;
  278. float value;
  279. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  280. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  281. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  282. plugin->setVolume(value, true, false);
  283. }
  284. else if (std::strcmp(msg, "set_balance_left") == 0)
  285. {
  286. uint32_t pluginId;
  287. float value;
  288. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  289. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  290. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  291. plugin->setBalanceLeft(value, true, false);
  292. }
  293. else if (std::strcmp(msg, "set_balance_right") == 0)
  294. {
  295. uint32_t pluginId;
  296. float value;
  297. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  298. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  299. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  300. plugin->setBalanceRight(value, true, false);
  301. }
  302. else if (std::strcmp(msg, "set_panning") == 0)
  303. {
  304. uint32_t pluginId;
  305. float value;
  306. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  307. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  308. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  309. plugin->setPanning(value, true, false);
  310. }
  311. else if (std::strcmp(msg, "set_ctrl_channel") == 0)
  312. {
  313. uint32_t pluginId;
  314. int32_t channel;
  315. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  316. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(channel), true);
  317. CARLA_SAFE_ASSERT_RETURN(channel >= -1 && channel < MAX_MIDI_CHANNELS, true);
  318. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  319. plugin->setCtrlChannel(int8_t(channel), true, false);
  320. }
  321. else if (std::strcmp(msg, "set_parameter_value") == 0)
  322. {
  323. uint32_t pluginId, parameterId;
  324. float value;
  325. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  326. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
  327. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  328. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  329. plugin->setParameterValue(parameterId, value, true, true, false);
  330. }
  331. else if (std::strcmp(msg, "set_parameter_midi_channel") == 0)
  332. {
  333. uint32_t pluginId, parameterId, channel;
  334. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  335. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
  336. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(channel), true);
  337. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, true);
  338. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  339. plugin->setParameterMidiChannel(parameterId, static_cast<uint8_t>(channel), true, false);
  340. }
  341. else if (std::strcmp(msg, "set_parameter_midi_cc") == 0)
  342. {
  343. uint32_t pluginId, parameterId;
  344. int32_t cc;
  345. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  346. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
  347. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(cc), true);
  348. CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < MAX_MIDI_CONTROL, true);
  349. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  350. plugin->setParameterMidiCC(parameterId, static_cast<int16_t>(cc), true, false);
  351. }
  352. else if (std::strcmp(msg, "set_program") == 0)
  353. {
  354. uint32_t pluginId;
  355. int32_t index;
  356. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  357. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index), true);
  358. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  359. {
  360. plugin->setProgram(index, true, true, false);
  361. _updateParamValues(plugin, pluginId);
  362. }
  363. }
  364. else if (std::strcmp(msg, "set_midi_program") == 0)
  365. {
  366. uint32_t pluginId;
  367. int32_t index;
  368. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  369. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index), true);
  370. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  371. {
  372. plugin->setMidiProgram(index, true, true, false);
  373. _updateParamValues(plugin, pluginId);
  374. }
  375. }
  376. else if (std::strcmp(msg, "set_custom_data") == 0)
  377. {
  378. uint32_t pluginId;
  379. const char* type;
  380. const char* key;
  381. const char* value;
  382. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  383. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(type), true);
  384. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(key), true);
  385. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(value), true);
  386. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  387. plugin->setCustomData(type, key, value, true);
  388. delete[] type;
  389. delete[] key;
  390. delete[] value;
  391. }
  392. else if (std::strcmp(msg, "set_chunk_data") == 0)
  393. {
  394. uint32_t pluginId;
  395. const char* cdata;
  396. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  397. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(cdata), true);
  398. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  399. {
  400. std::vector<uint8_t> chunk(carla_getChunkFromBase64String(cdata));
  401. #ifdef CARLA_PROPER_CPP11_SUPPORT
  402. plugin->setChunkData(chunk.data(), chunk.size());
  403. #else
  404. plugin->setChunkData(&chunk.front(), chunk.size());
  405. #endif
  406. }
  407. delete[] cdata;
  408. }
  409. else if (std::strcmp(msg, "prepare_for_save") == 0)
  410. {
  411. uint32_t pluginId;
  412. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  413. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  414. plugin->prepareForSave();
  415. }
  416. else if (std::strcmp(msg, "reset_parameters") == 0)
  417. {
  418. uint32_t pluginId;
  419. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  420. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  421. plugin->resetParameters();
  422. }
  423. else if (std::strcmp(msg, "randomize_parameters") == 0)
  424. {
  425. uint32_t pluginId;
  426. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  427. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  428. plugin->randomizeParameters();
  429. }
  430. else if (std::strcmp(msg, "send_midi_note") == 0)
  431. {
  432. uint32_t pluginId, channel, note, velocity;
  433. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  434. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(channel), true);
  435. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(note), true);
  436. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(velocity), true);
  437. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, true);
  438. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_VALUE, true);
  439. CARLA_SAFE_ASSERT_RETURN(velocity < MAX_MIDI_VALUE, true);
  440. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  441. plugin->sendMidiSingleNote(static_cast<uint8_t>(channel), static_cast<uint8_t>(note), static_cast<uint8_t>(velocity), true, true, false);
  442. }
  443. else if (std::strcmp(msg, "show_custom_ui") == 0)
  444. {
  445. uint32_t pluginId;
  446. bool yesNo;
  447. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  448. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo), true);
  449. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  450. plugin->showCustomUI(yesNo);
  451. }
  452. else if (std::strcmp(msg, "ready") == 0)
  453. {
  454. uint64_t winId;
  455. CARLA_SAFE_ASSERT_RETURN(readNextLineAsULong(winId), true);
  456. fRemoteWinId = static_cast<intptr_t>(winId);
  457. }
  458. else
  459. {
  460. carla_stderr("CarlaEngineNativeUI::msgReceived : %s", msg);
  461. return false;
  462. }
  463. if (! ok)
  464. {
  465. const CarlaMutexLocker cml(getPipeLock());
  466. if (writeMessage("error\n", 6) && writeAndFixMessage(fEngine->getLastError()))
  467. flushMessages();
  468. }
  469. return true;
  470. }
  471. private:
  472. CarlaEngine* const fEngine;
  473. intptr_t fRemoteWinId;
  474. void _updateParamValues(CarlaPlugin* const plugin, const uint32_t pluginId) const noexcept
  475. {
  476. for (uint32_t i=0, count=plugin->getParameterCount(); i<count; ++i)
  477. fEngine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  478. pluginId, static_cast<int>(i), 0, plugin->getParameterValue(i), nullptr);
  479. }
  480. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNativeUI)
  481. };
  482. // -----------------------------------------------------------------------
  483. class CarlaEngineNative : public CarlaEngine
  484. {
  485. public:
  486. CarlaEngineNative(const NativeHostDescriptor* const host, const bool isPatchbay, const bool withMidiOut,
  487. const uint32_t inChan = 2, uint32_t outChan = 2)
  488. : CarlaEngine(),
  489. pHost(host),
  490. kIsPatchbay(isPatchbay),
  491. kHasMidiOut(withMidiOut),
  492. fIsActive(false),
  493. fIsRunning(false),
  494. fUiServer(this),
  495. fOptionsForced(false),
  496. fWaitForReadyMsg(false)
  497. {
  498. carla_debug("CarlaEngineNative::CarlaEngineNative()");
  499. pData->bufferSize = pHost->get_buffer_size(pHost->handle);
  500. pData->sampleRate = pHost->get_sample_rate(pHost->handle);
  501. pData->initTime(nullptr);
  502. if (outChan == 0)
  503. outChan = inChan;
  504. // set-up engine
  505. if (kIsPatchbay)
  506. {
  507. pData->options.processMode = ENGINE_PROCESS_MODE_PATCHBAY;
  508. pData->options.transportMode = ENGINE_TRANSPORT_MODE_PLUGIN;
  509. pData->options.forceStereo = false;
  510. pData->options.preferPluginBridges = false;
  511. pData->options.preferUiBridges = false;
  512. init("Carla-Patchbay");
  513. pData->graph.create(inChan, outChan);
  514. }
  515. else
  516. {
  517. CARLA_SAFE_ASSERT(inChan == 2);
  518. CARLA_SAFE_ASSERT(outChan == 2);
  519. pData->options.processMode = ENGINE_PROCESS_MODE_CONTINUOUS_RACK;
  520. pData->options.transportMode = ENGINE_TRANSPORT_MODE_PLUGIN;
  521. pData->options.forceStereo = true;
  522. pData->options.preferPluginBridges = false;
  523. pData->options.preferUiBridges = false;
  524. init("Carla-Rack");
  525. pData->graph.create(0, 0); // FIXME?
  526. }
  527. if (pData->options.resourceDir != nullptr)
  528. delete[] pData->options.resourceDir;
  529. if (pData->options.binaryDir != nullptr)
  530. delete[] pData->options.binaryDir;
  531. pData->options.resourceDir = carla_strdup(pHost->resourceDir);
  532. pData->options.binaryDir = carla_strdup(carla_get_library_folder());
  533. setCallback(_ui_server_callback, this);
  534. }
  535. ~CarlaEngineNative() override
  536. {
  537. CARLA_SAFE_ASSERT(! fIsActive);
  538. carla_debug("CarlaEngineNative::~CarlaEngineNative() - START");
  539. pData->aboutToClose = true;
  540. fIsRunning = false;
  541. removeAllPlugins();
  542. //runPendingRtEvents();
  543. close();
  544. pData->graph.destroy();
  545. carla_debug("CarlaEngineNative::~CarlaEngineNative() - END");
  546. }
  547. protected:
  548. // -------------------------------------
  549. // CarlaEngine virtual calls
  550. bool init(const char* const clientName) override
  551. {
  552. carla_debug("CarlaEngineNative::init(\"%s\")", clientName);
  553. fIsRunning = true;
  554. if (! pData->init(clientName))
  555. {
  556. close();
  557. setLastError("Failed to init internal data");
  558. return false;
  559. }
  560. pData->bufferSize = pHost->get_buffer_size(pHost->handle);
  561. pData->sampleRate = pHost->get_sample_rate(pHost->handle);
  562. return true;
  563. }
  564. bool close() override
  565. {
  566. fIsRunning = false;
  567. CarlaEngine::close();
  568. return true;
  569. }
  570. bool isRunning() const noexcept override
  571. {
  572. return fIsRunning;
  573. }
  574. bool isOffline() const noexcept override
  575. {
  576. return pHost->is_offline(pHost->handle);
  577. }
  578. bool usesConstantBufferSize() const noexcept override
  579. {
  580. // TODO
  581. return true;
  582. }
  583. EngineType getType() const noexcept override
  584. {
  585. return kEngineTypePlugin;
  586. }
  587. const char* getCurrentDriverName() const noexcept override
  588. {
  589. return "Plugin";
  590. }
  591. void callback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const float value3, const char* const valueStr) noexcept override
  592. {
  593. CarlaEngine::callback(action, pluginId, value1, value2, value3, valueStr);
  594. if (action == ENGINE_CALLBACK_IDLE && ! pData->aboutToClose)
  595. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_HOST_IDLE, 0, 0, nullptr, 0.0f);
  596. }
  597. // -------------------------------------------------------------------
  598. const char* renamePlugin(const uint id, const char* const newName) override
  599. {
  600. if (const char* const retName = CarlaEngine::renamePlugin(id, newName))
  601. {
  602. uiServerCallback(ENGINE_CALLBACK_PLUGIN_RENAMED, id, 0, 0, 0.0f, retName);
  603. return retName;
  604. }
  605. return nullptr;
  606. }
  607. // -------------------------------------------------------------------
  608. void bufferSizeChanged(const uint32_t newBufferSize)
  609. {
  610. if (pData->bufferSize == newBufferSize)
  611. return;
  612. {
  613. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  614. if (fUiServer.writeAndFixMessage("buffer-size"))
  615. {
  616. char tmpBuf[STR_MAX];
  617. carla_zeroChars(tmpBuf, STR_MAX);
  618. std::sprintf(tmpBuf, "%i\n", newBufferSize);
  619. if (fUiServer.writeMessage(tmpBuf))
  620. fUiServer.flushMessages();
  621. }
  622. }
  623. pData->bufferSize = newBufferSize;
  624. CarlaEngine::bufferSizeChanged(newBufferSize);
  625. }
  626. void sampleRateChanged(const double newSampleRate)
  627. {
  628. if (carla_isEqual(pData->sampleRate, newSampleRate))
  629. return;
  630. {
  631. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  632. if (fUiServer.writeAndFixMessage("sample-rate"))
  633. {
  634. char tmpBuf[STR_MAX];
  635. carla_zeroChars(tmpBuf, STR_MAX);
  636. {
  637. const ScopedLocale csl;
  638. std::sprintf(tmpBuf, "%f\n", newSampleRate);
  639. }
  640. if (fUiServer.writeMessage(tmpBuf))
  641. fUiServer.flushMessages();
  642. }
  643. }
  644. pData->sampleRate = newSampleRate;
  645. CarlaEngine::sampleRateChanged(newSampleRate);
  646. }
  647. // -------------------------------------------------------------------
  648. void uiServerSendPluginInfo(CarlaPlugin* const plugin)
  649. {
  650. char tmpBuf[STR_MAX];
  651. carla_zeroChars(tmpBuf, STR_MAX);
  652. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  653. const uint pluginId(plugin->getId());
  654. std::sprintf(tmpBuf, "PLUGIN_INFO_%i\n", pluginId);
  655. if (! fUiServer.writeMessage(tmpBuf))
  656. return;
  657. std::sprintf(tmpBuf, "%i:%i:%i:" P_INT64 ":%i:%i\n", plugin->getType(), plugin->getCategory(), plugin->getHints(), plugin->getUniqueId(), plugin->getOptionsAvailable(), plugin->getOptionsEnabled());
  658. if (! fUiServer.writeMessage(tmpBuf))
  659. return;
  660. if (const char* const filename = plugin->getFilename())
  661. {
  662. std::sprintf(tmpBuf, "%s", filename);
  663. if (! fUiServer.writeAndFixMessage(tmpBuf))
  664. return;
  665. }
  666. else
  667. {
  668. if (! fUiServer.writeMessage("\n"))
  669. return;
  670. }
  671. if (const char* const name = plugin->getName())
  672. {
  673. std::sprintf(tmpBuf, "%s", name);
  674. if (! fUiServer.writeAndFixMessage(tmpBuf))
  675. return;
  676. }
  677. else
  678. {
  679. if (! fUiServer.writeMessage("\n"))
  680. return;
  681. }
  682. if (const char* const iconName = plugin->getIconName())
  683. {
  684. std::sprintf(tmpBuf, "%s", iconName);
  685. if (! fUiServer.writeAndFixMessage(tmpBuf))
  686. return;
  687. }
  688. else
  689. {
  690. if (! fUiServer.writeMessage("\n"))
  691. return;
  692. }
  693. plugin->getRealName(tmpBuf);
  694. if (! fUiServer.writeAndFixMessage(tmpBuf))
  695. return;
  696. plugin->getLabel(tmpBuf);
  697. if (! fUiServer.writeAndFixMessage(tmpBuf))
  698. return;
  699. plugin->getMaker(tmpBuf);
  700. if (! fUiServer.writeAndFixMessage(tmpBuf))
  701. return;
  702. plugin->getCopyright(tmpBuf);
  703. if (! fUiServer.writeAndFixMessage(tmpBuf))
  704. return;
  705. std::sprintf(tmpBuf, "AUDIO_COUNT_%i:%i:%i\n", pluginId, plugin->getAudioInCount(), plugin->getAudioOutCount());
  706. if (! fUiServer.writeMessage(tmpBuf))
  707. return;
  708. std::sprintf(tmpBuf, "MIDI_COUNT_%i:%i:%i\n", pluginId, plugin->getMidiInCount(), plugin->getMidiOutCount());
  709. if (! fUiServer.writeMessage(tmpBuf))
  710. return;
  711. fUiServer.flushMessages();
  712. }
  713. void uiServerSendPluginParameters(CarlaPlugin* const plugin)
  714. {
  715. char tmpBuf[STR_MAX];
  716. carla_zeroChars(tmpBuf, STR_MAX);
  717. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  718. const ScopedLocale csl;
  719. const uint pluginId(plugin->getId());
  720. for (int32_t i=PARAMETER_ACTIVE; i>PARAMETER_MAX; --i)
  721. {
  722. std::sprintf(tmpBuf, "PARAMVAL_%i:%i\n", pluginId, i);
  723. if (! fUiServer.writeMessage(tmpBuf))
  724. return;
  725. std::sprintf(tmpBuf, "%f\n", plugin->getInternalParameterValue(i));
  726. if (! fUiServer.writeMessage(tmpBuf))
  727. return;
  728. fUiServer.flushMessages();
  729. }
  730. uint32_t ins, outs, count;
  731. plugin->getParameterCountInfo(ins, outs);
  732. count = plugin->getParameterCount();
  733. std::sprintf(tmpBuf, "PARAMETER_COUNT_%i:%i:%i:%i\n", pluginId, ins, outs, count);
  734. if (! fUiServer.writeMessage(tmpBuf))
  735. return;
  736. for (uint32_t i=0; i<count; ++i)
  737. {
  738. const ParameterData& paramData(plugin->getParameterData(i));
  739. const ParameterRanges& paramRanges(plugin->getParameterRanges(i));
  740. std::sprintf(tmpBuf, "PARAMETER_DATA_%i:%i\n", pluginId, i);
  741. if (! fUiServer.writeMessage(tmpBuf))
  742. return;
  743. std::sprintf(tmpBuf, "%i:%i:%i:%i\n", paramData.type, paramData.hints, paramData.midiChannel, paramData.midiCC);
  744. if (! fUiServer.writeMessage(tmpBuf))
  745. return;
  746. plugin->getParameterName(i, tmpBuf);
  747. if (! fUiServer.writeAndFixMessage(tmpBuf))
  748. return;
  749. plugin->getParameterUnit(i, tmpBuf);
  750. if (! fUiServer.writeAndFixMessage(tmpBuf))
  751. return;
  752. std::sprintf(tmpBuf, "PARAMETER_RANGES_%i:%i\n", pluginId, i);
  753. if (! fUiServer.writeMessage(tmpBuf))
  754. return;
  755. std::sprintf(tmpBuf, "%f:%f:%f:%f:%f:%f\n", paramRanges.def, paramRanges.min, paramRanges.max, paramRanges.step, paramRanges.stepSmall, paramRanges.stepLarge);
  756. if (! fUiServer.writeMessage(tmpBuf))
  757. return;
  758. std::sprintf(tmpBuf, "PARAMVAL_%i:%i\n", pluginId, i);
  759. if (! fUiServer.writeMessage(tmpBuf))
  760. return;
  761. std::sprintf(tmpBuf, "%f\n", plugin->getParameterValue(i));
  762. if (! fUiServer.writeMessage(tmpBuf))
  763. return;
  764. }
  765. fUiServer.flushMessages();
  766. }
  767. void uiServerSendPluginPrograms(CarlaPlugin* const plugin)
  768. {
  769. char tmpBuf[STR_MAX];
  770. carla_zeroChars(tmpBuf, STR_MAX);
  771. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  772. const uint pluginId(plugin->getId());
  773. uint32_t count = plugin->getProgramCount();
  774. std::sprintf(tmpBuf, "PROGRAM_COUNT_%i:%i:%i\n", pluginId, count, plugin->getCurrentProgram());
  775. if (! fUiServer.writeMessage(tmpBuf))
  776. return;
  777. for (uint32_t i=0; i<count; ++i)
  778. {
  779. std::sprintf(tmpBuf, "PROGRAM_NAME_%i:%i\n", pluginId, i);
  780. if (! fUiServer.writeMessage(tmpBuf))
  781. return;
  782. plugin->getProgramName(i, tmpBuf);
  783. if (! fUiServer.writeAndFixMessage(tmpBuf))
  784. return;
  785. }
  786. fUiServer.flushMessages();
  787. count = plugin->getMidiProgramCount();
  788. std::sprintf(tmpBuf, "MIDI_PROGRAM_COUNT_%i:%i:%i\n", pluginId, count, plugin->getCurrentMidiProgram());
  789. if (! fUiServer.writeMessage(tmpBuf))
  790. return;
  791. for (uint32_t i=0; i<count; ++i)
  792. {
  793. std::sprintf(tmpBuf, "MIDI_PROGRAM_DATA_%i:%i\n", pluginId, i);
  794. if (! fUiServer.writeMessage(tmpBuf))
  795. return;
  796. const MidiProgramData& mpData(plugin->getMidiProgramData(i));
  797. std::sprintf(tmpBuf, "%i:%i\n", mpData.bank, mpData.program);
  798. if (! fUiServer.writeMessage(tmpBuf))
  799. return;
  800. std::sprintf(tmpBuf, "%s", mpData.name);
  801. if (! fUiServer.writeAndFixMessage(tmpBuf))
  802. return;
  803. }
  804. fUiServer.flushMessages();
  805. }
  806. void uiServerSendPluginProperties(CarlaPlugin* const plugin)
  807. {
  808. char tmpBuf[STR_MAX];
  809. carla_zeroChars(tmpBuf, STR_MAX);
  810. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  811. const uint pluginId(plugin->getId());
  812. uint32_t count = plugin->getCustomDataCount();
  813. std::sprintf(tmpBuf, "CUSTOM_DATA_COUNT_%i:%i\n", pluginId, count);
  814. if (! fUiServer.writeMessage(tmpBuf))
  815. return;
  816. for (uint32_t i=0; i<count; ++i)
  817. {
  818. const CustomData& customData(plugin->getCustomData(i));
  819. CARLA_SAFE_ASSERT_CONTINUE(customData.isValid());
  820. if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_PROPERTY) != 0)
  821. continue;
  822. std::sprintf(tmpBuf, "CUSTOM_DATA_%i:%i\n", pluginId, i);
  823. if (! fUiServer.writeMessage(tmpBuf))
  824. return;
  825. if (! fUiServer.writeAndFixMessage(customData.type))
  826. return;
  827. if (! fUiServer.writeAndFixMessage(customData.key))
  828. return;
  829. if (! fUiServer.writeAndFixMessage(customData.value))
  830. return;
  831. }
  832. fUiServer.flushMessages();
  833. }
  834. void uiServerCallback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const float value3, const char* const valueStr)
  835. {
  836. if (! fIsRunning)
  837. return;
  838. if (! fUiServer.isPipeRunning())
  839. return;
  840. CarlaPlugin* plugin;
  841. switch (action)
  842. {
  843. case ENGINE_CALLBACK_UPDATE:
  844. plugin = getPlugin(pluginId);
  845. if (plugin != nullptr && plugin->isEnabled())
  846. {
  847. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  848. uiServerSendPluginProperties(plugin);
  849. }
  850. break;
  851. case ENGINE_CALLBACK_RELOAD_INFO:
  852. plugin = getPlugin(pluginId);
  853. if (plugin != nullptr && plugin->isEnabled())
  854. {
  855. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  856. uiServerSendPluginInfo(plugin);
  857. }
  858. break;
  859. case ENGINE_CALLBACK_RELOAD_PARAMETERS:
  860. plugin = getPlugin(pluginId);
  861. if (plugin != nullptr && plugin->isEnabled())
  862. {
  863. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  864. uiServerSendPluginParameters(plugin);
  865. }
  866. break;
  867. case ENGINE_CALLBACK_RELOAD_PROGRAMS:
  868. plugin = getPlugin(pluginId);
  869. if (plugin != nullptr && plugin->isEnabled())
  870. {
  871. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  872. uiServerSendPluginPrograms(plugin);
  873. }
  874. break;
  875. case ENGINE_CALLBACK_RELOAD_ALL:
  876. case ENGINE_CALLBACK_PLUGIN_ADDED:
  877. plugin = getPlugin(pluginId);
  878. if (plugin != nullptr && plugin->isEnabled())
  879. {
  880. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  881. uiServerSendPluginInfo(plugin);
  882. uiServerSendPluginParameters(plugin);
  883. uiServerSendPluginPrograms(plugin);
  884. uiServerSendPluginProperties(plugin);
  885. }
  886. break;
  887. default:
  888. break;
  889. }
  890. char tmpBuf[STR_MAX];
  891. carla_zeroChars(tmpBuf, STR_MAX);
  892. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  893. std::sprintf(tmpBuf, "ENGINE_CALLBACK_%i\n", int(action));
  894. if (! fUiServer.writeMessage(tmpBuf))
  895. return;
  896. std::sprintf(tmpBuf, "%u\n", pluginId);
  897. if (! fUiServer.writeMessage(tmpBuf))
  898. return;
  899. std::sprintf(tmpBuf, "%i\n", value1);
  900. if (! fUiServer.writeMessage(tmpBuf))
  901. return;
  902. std::sprintf(tmpBuf, "%i\n", value2);
  903. if (! fUiServer.writeMessage(tmpBuf))
  904. return;
  905. {
  906. const ScopedLocale csl;
  907. std::sprintf(tmpBuf, "%f\n", value3);
  908. }
  909. if (! fUiServer.writeMessage(tmpBuf))
  910. return;
  911. if (! fUiServer.writeAndFixMessage(valueStr != nullptr ? valueStr : ""))
  912. return;
  913. fUiServer.flushMessages();
  914. }
  915. void uiServerInfo()
  916. {
  917. CARLA_SAFE_ASSERT_RETURN(fIsRunning,);
  918. CARLA_SAFE_ASSERT_RETURN(fUiServer.isPipeRunning(),);
  919. char tmpBuf[STR_MAX];
  920. carla_zeroChars(tmpBuf, STR_MAX);
  921. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  922. #ifdef HAVE_LIBLO
  923. if (! fUiServer.writeAndFixMessage("osc-urls"))
  924. return;
  925. if (! fUiServer.writeAndFixMessage(pData->osc.getServerPathTCP()))
  926. return;
  927. if (! fUiServer.writeAndFixMessage(pData->osc.getServerPathUDP()))
  928. return;
  929. #endif
  930. if (! fUiServer.writeAndFixMessage("max-plugin-number"))
  931. return;
  932. std::sprintf(tmpBuf, "%i\n", pData->maxPluginNumber);
  933. if (! fUiServer.writeMessage(tmpBuf))
  934. return;
  935. if (! fUiServer.writeAndFixMessage("buffer-size"))
  936. return;
  937. std::sprintf(tmpBuf, "%i\n", pData->bufferSize);
  938. if (! fUiServer.writeMessage(tmpBuf))
  939. return;
  940. if (! fUiServer.writeAndFixMessage("sample-rate"))
  941. return;
  942. {
  943. const ScopedLocale csl;
  944. std::sprintf(tmpBuf, "%f\n", pData->sampleRate);
  945. }
  946. if (! fUiServer.writeMessage(tmpBuf))
  947. return;
  948. fUiServer.flushMessages();
  949. }
  950. void uiServerOptions()
  951. {
  952. CARLA_SAFE_ASSERT_RETURN(fIsRunning,);
  953. CARLA_SAFE_ASSERT_RETURN(fUiServer.isPipeRunning(),);
  954. char tmpBuf[STR_MAX];
  955. carla_zeroChars(tmpBuf, STR_MAX);
  956. const EngineOptions& options(pData->options);
  957. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  958. const char* const optionsForcedStr(fOptionsForced ? "true\n" : "false\n");
  959. const std::size_t optionsForcedStrSize(fOptionsForced ? 5 : 6);
  960. std::sprintf(tmpBuf, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PROCESS_MODE);
  961. if (! fUiServer.writeMessage(tmpBuf))
  962. return;
  963. if (! fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize))
  964. return;
  965. std::sprintf(tmpBuf, "%i\n", options.processMode);
  966. if (! fUiServer.writeMessage(tmpBuf))
  967. return;
  968. fUiServer.flushMessages();
  969. std::sprintf(tmpBuf, "ENGINE_OPTION_%i\n", ENGINE_OPTION_TRANSPORT_MODE);
  970. if (! fUiServer.writeMessage(tmpBuf))
  971. return;
  972. if (! fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize))
  973. return;
  974. std::sprintf(tmpBuf, "%i\n", options.transportMode);
  975. if (! fUiServer.writeMessage(tmpBuf))
  976. return;
  977. fUiServer.flushMessages();
  978. std::sprintf(tmpBuf, "ENGINE_OPTION_%i\n", ENGINE_OPTION_FORCE_STEREO);
  979. if (! fUiServer.writeMessage(tmpBuf))
  980. return;
  981. if (! fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize))
  982. return;
  983. if (! fUiServer.writeMessage(options.forceStereo ? "true\n" : "false\n"))
  984. return;
  985. fUiServer.flushMessages();
  986. std::sprintf(tmpBuf, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PREFER_PLUGIN_BRIDGES);
  987. if (! fUiServer.writeMessage(tmpBuf))
  988. return;
  989. if (! fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize))
  990. return;
  991. if (! fUiServer.writeMessage(options.preferPluginBridges ? "true\n" : "false\n"))
  992. return;
  993. fUiServer.flushMessages();
  994. std::sprintf(tmpBuf, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PREFER_UI_BRIDGES);
  995. if (! fUiServer.writeMessage(tmpBuf))
  996. return;
  997. if (! fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize))
  998. return;
  999. if (! fUiServer.writeMessage(options.preferUiBridges ? "true\n" : "false\n"))
  1000. return;
  1001. fUiServer.flushMessages();
  1002. std::sprintf(tmpBuf, "ENGINE_OPTION_%i\n", ENGINE_OPTION_UIS_ALWAYS_ON_TOP);
  1003. if (! fUiServer.writeMessage(tmpBuf))
  1004. return;
  1005. if (! fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize))
  1006. return;
  1007. if (! fUiServer.writeMessage(options.uisAlwaysOnTop ? "true\n" : "false\n"))
  1008. return;
  1009. fUiServer.flushMessages();
  1010. std::sprintf(tmpBuf, "ENGINE_OPTION_%i\n", ENGINE_OPTION_MAX_PARAMETERS);
  1011. if (! fUiServer.writeMessage(tmpBuf))
  1012. return;
  1013. if (! fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize))
  1014. return;
  1015. std::sprintf(tmpBuf, "%i\n", options.maxParameters);
  1016. if (! fUiServer.writeMessage(tmpBuf))
  1017. return;
  1018. fUiServer.flushMessages();
  1019. std::sprintf(tmpBuf, "ENGINE_OPTION_%i\n", ENGINE_OPTION_UI_BRIDGES_TIMEOUT);
  1020. if (! fUiServer.writeMessage(tmpBuf))
  1021. return;
  1022. if (! fUiServer.writeMessage(optionsForcedStr, optionsForcedStrSize))
  1023. return;
  1024. std::sprintf(tmpBuf, "%i\n", options.uiBridgesTimeout);
  1025. if (! fUiServer.writeMessage(tmpBuf))
  1026. return;
  1027. fUiServer.flushMessages();
  1028. std::sprintf(tmpBuf, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PATH_BINARIES);
  1029. if (! fUiServer.writeMessage(tmpBuf))
  1030. return;
  1031. if (! fUiServer.writeMessage("true\n", 5))
  1032. return;
  1033. std::sprintf(tmpBuf, "%s\n", options.binaryDir);
  1034. if (! fUiServer.writeMessage(tmpBuf))
  1035. return;
  1036. fUiServer.flushMessages();
  1037. std::sprintf(tmpBuf, "ENGINE_OPTION_%i\n", ENGINE_OPTION_PATH_RESOURCES);
  1038. if (! fUiServer.writeMessage(tmpBuf))
  1039. return;
  1040. if (! fUiServer.writeMessage("true\n", 5))
  1041. return;
  1042. std::sprintf(tmpBuf, "%s\n", options.resourceDir);
  1043. if (! fUiServer.writeMessage(tmpBuf))
  1044. return;
  1045. fUiServer.flushMessages();
  1046. }
  1047. // -------------------------------------------------------------------
  1048. // Plugin parameter calls
  1049. uint32_t getParameterCount() const
  1050. {
  1051. if (CarlaPlugin* const plugin = _getFirstPlugin())
  1052. return plugin->getParameterCount();
  1053. return 0;
  1054. }
  1055. const NativeParameter* getParameterInfo(const uint32_t index) const
  1056. {
  1057. if (CarlaPlugin* const plugin = _getFirstPlugin())
  1058. {
  1059. if (index < plugin->getParameterCount())
  1060. {
  1061. static NativeParameter param;
  1062. static char strBufName[STR_MAX+1];
  1063. static char strBufUnit[STR_MAX+1];
  1064. const ParameterData& paramData(plugin->getParameterData(index));
  1065. const ParameterRanges& paramRanges(plugin->getParameterRanges(index));
  1066. plugin->getParameterName(index, strBufName);
  1067. plugin->getParameterUnit(index, strBufUnit);
  1068. uint hints = 0x0;
  1069. if (paramData.hints & PARAMETER_IS_BOOLEAN)
  1070. hints |= NATIVE_PARAMETER_IS_BOOLEAN;
  1071. if (paramData.hints & PARAMETER_IS_INTEGER)
  1072. hints |= NATIVE_PARAMETER_IS_INTEGER;
  1073. if (paramData.hints & PARAMETER_IS_LOGARITHMIC)
  1074. hints |= NATIVE_PARAMETER_IS_LOGARITHMIC;
  1075. if (paramData.hints & PARAMETER_IS_AUTOMABLE)
  1076. hints |= NATIVE_PARAMETER_IS_AUTOMABLE;
  1077. if (paramData.hints & PARAMETER_USES_SAMPLERATE)
  1078. hints |= NATIVE_PARAMETER_USES_SAMPLE_RATE;
  1079. if (paramData.hints & PARAMETER_USES_SCALEPOINTS)
  1080. hints |= NATIVE_PARAMETER_USES_SCALEPOINTS;
  1081. if (paramData.type == PARAMETER_INPUT || paramData.type == PARAMETER_OUTPUT)
  1082. {
  1083. if (paramData.hints & PARAMETER_IS_ENABLED)
  1084. hints |= NATIVE_PARAMETER_IS_ENABLED;
  1085. if (paramData.type == PARAMETER_OUTPUT)
  1086. hints |= NATIVE_PARAMETER_IS_OUTPUT;
  1087. }
  1088. param.hints = static_cast<NativeParameterHints>(hints);
  1089. param.name = strBufName;
  1090. param.unit = strBufUnit;
  1091. param.ranges.def = paramRanges.def;
  1092. param.ranges.min = paramRanges.min;
  1093. param.ranges.max = paramRanges.max;
  1094. param.ranges.step = paramRanges.step;
  1095. param.ranges.stepSmall = paramRanges.stepSmall;
  1096. param.ranges.stepLarge = paramRanges.stepLarge;
  1097. param.scalePointCount = 0; // TODO
  1098. param.scalePoints = nullptr;
  1099. return &param;
  1100. }
  1101. }
  1102. return nullptr;
  1103. }
  1104. float getParameterValue(const uint32_t index) const
  1105. {
  1106. if (CarlaPlugin* const plugin = _getFirstPlugin())
  1107. {
  1108. if (index < plugin->getParameterCount())
  1109. return plugin->getParameterValue(index);
  1110. }
  1111. return 0.0f;
  1112. }
  1113. // -------------------------------------------------------------------
  1114. // Plugin midi-program calls
  1115. uint32_t getMidiProgramCount() const
  1116. {
  1117. if (CarlaPlugin* const plugin = _getFirstPlugin())
  1118. return plugin->getMidiProgramCount();
  1119. return 0;
  1120. }
  1121. const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const
  1122. {
  1123. if (CarlaPlugin* const plugin = _getFirstPlugin())
  1124. {
  1125. if (index < plugin->getMidiProgramCount())
  1126. {
  1127. static NativeMidiProgram midiProg;
  1128. {
  1129. const MidiProgramData& midiProgData(plugin->getMidiProgramData(index));
  1130. midiProg.bank = midiProgData.bank;
  1131. midiProg.program = midiProgData.program;
  1132. midiProg.name = midiProgData.name;
  1133. }
  1134. return &midiProg;
  1135. }
  1136. }
  1137. return nullptr;
  1138. }
  1139. // -------------------------------------------------------------------
  1140. // Plugin state calls
  1141. void setParameterValue(const uint32_t index, const float value)
  1142. {
  1143. if (CarlaPlugin* const plugin = _getFirstPlugin())
  1144. {
  1145. if (index < plugin->getParameterCount())
  1146. plugin->setParameterValue(index, value, false, false, false);
  1147. }
  1148. }
  1149. void setMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program)
  1150. {
  1151. if (CarlaPlugin* const plugin = _getFirstPlugin())
  1152. plugin->setMidiProgramById(bank, program, false, false, false);
  1153. }
  1154. // -------------------------------------------------------------------
  1155. // Plugin process calls
  1156. void activate()
  1157. {
  1158. #if 0
  1159. for (uint i=0; i < pData->curPluginCount; ++i)
  1160. {
  1161. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1162. if (plugin == nullptr || ! plugin->isEnabled())
  1163. continue;
  1164. plugin->setActive(true, true, false);
  1165. }
  1166. #endif
  1167. fIsActive = true;
  1168. }
  1169. void deactivate()
  1170. {
  1171. fIsActive = false;
  1172. #if 0
  1173. for (uint i=0; i < pData->curPluginCount; ++i)
  1174. {
  1175. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1176. if (plugin == nullptr || ! plugin->isEnabled())
  1177. continue;
  1178. plugin->setActive(false, true, false);
  1179. }
  1180. #endif
  1181. // just in case
  1182. //runPendingRtEvents();
  1183. }
  1184. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames,
  1185. const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount)
  1186. {
  1187. const PendingRtEventsRunner prt(this, frames);
  1188. // ---------------------------------------------------------------
  1189. // Time Info
  1190. const NativeTimeInfo* const timeInfo(pHost->get_time_info(pHost->handle));
  1191. pData->timeInfo.playing = timeInfo->playing;
  1192. pData->timeInfo.frame = timeInfo->frame;
  1193. pData->timeInfo.usecs = timeInfo->usecs;
  1194. pData->timeInfo.bbt.valid = timeInfo->bbt.valid;
  1195. if (timeInfo->bbt.valid)
  1196. {
  1197. pData->timeInfo.bbt.bar = timeInfo->bbt.bar;
  1198. pData->timeInfo.bbt.beat = timeInfo->bbt.beat;
  1199. pData->timeInfo.bbt.tick = timeInfo->bbt.tick;
  1200. pData->timeInfo.bbt.barStartTick = timeInfo->bbt.barStartTick;
  1201. pData->timeInfo.bbt.beatsPerBar = timeInfo->bbt.beatsPerBar;
  1202. pData->timeInfo.bbt.beatType = timeInfo->bbt.beatType;
  1203. pData->timeInfo.bbt.ticksPerBeat = timeInfo->bbt.ticksPerBeat;
  1204. pData->timeInfo.bbt.beatsPerMinute = timeInfo->bbt.beatsPerMinute;
  1205. }
  1206. // ---------------------------------------------------------------
  1207. // Do nothing if no plugins and rack mode
  1208. if (pData->curPluginCount == 0 && ! kIsPatchbay)
  1209. {
  1210. if (outBuffer[0] != inBuffer[0])
  1211. carla_copyFloats(outBuffer[0], inBuffer[0], frames);
  1212. if (outBuffer[1] != inBuffer[1])
  1213. carla_copyFloats(outBuffer[1], inBuffer[1], frames);
  1214. for (uint32_t i=0; i < midiEventCount; ++i)
  1215. {
  1216. if (! pHost->write_midi_event(pHost->handle, &midiEvents[i]))
  1217. break;
  1218. }
  1219. return;
  1220. }
  1221. // ---------------------------------------------------------------
  1222. // initialize events
  1223. carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount);
  1224. carla_zeroStructs(pData->events.out, kMaxEngineEventInternalCount);
  1225. // ---------------------------------------------------------------
  1226. // events input (before processing)
  1227. {
  1228. uint32_t engineEventIndex = 0;
  1229. for (uint32_t i=0; i < midiEventCount && engineEventIndex < kMaxEngineEventInternalCount; ++i)
  1230. {
  1231. const NativeMidiEvent& midiEvent(midiEvents[i]);
  1232. EngineEvent& engineEvent(pData->events.in[engineEventIndex++]);
  1233. engineEvent.time = midiEvent.time;
  1234. engineEvent.fillFromMidiData(midiEvent.size, midiEvent.data, 0);
  1235. if (engineEventIndex >= kMaxEngineEventInternalCount)
  1236. break;
  1237. }
  1238. }
  1239. if (kIsPatchbay)
  1240. {
  1241. // -----------------------------------------------------------
  1242. // process
  1243. pData->graph.process(pData, inBuffer, outBuffer, frames);
  1244. }
  1245. else
  1246. {
  1247. // -----------------------------------------------------------
  1248. // create audio buffers
  1249. const float* inBuf[2] = { inBuffer[0], inBuffer[1] };
  1250. /* */ float* outBuf[2] = { outBuffer[0], outBuffer[1] };
  1251. // -----------------------------------------------------------
  1252. // process
  1253. pData->graph.processRack(pData, inBuf, outBuf, frames);
  1254. }
  1255. // ---------------------------------------------------------------
  1256. // events output (after processing)
  1257. carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount);
  1258. if (kHasMidiOut)
  1259. {
  1260. NativeMidiEvent midiEvent;
  1261. for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i)
  1262. {
  1263. const EngineEvent& engineEvent(pData->events.out[i]);
  1264. if (engineEvent.type == kEngineEventTypeNull)
  1265. break;
  1266. carla_zeroStruct(midiEvent);
  1267. midiEvent.time = engineEvent.time;
  1268. /**/ if (engineEvent.type == kEngineEventTypeControl)
  1269. {
  1270. midiEvent.port = 0;
  1271. midiEvent.size = engineEvent.ctrl.convertToMidiData(engineEvent.channel, midiEvent.data);
  1272. }
  1273. else if (engineEvent.type == kEngineEventTypeMidi)
  1274. {
  1275. if (engineEvent.midi.size > 4)
  1276. continue;
  1277. midiEvent.port = engineEvent.midi.port;
  1278. midiEvent.size = engineEvent.midi.size;
  1279. midiEvent.data[0] = static_cast<uint8_t>(engineEvent.midi.data[0] | (engineEvent.channel & MIDI_CHANNEL_BIT));
  1280. for (uint8_t j=1; j < midiEvent.size; ++j)
  1281. midiEvent.data[j] = engineEvent.midi.data[j];
  1282. }
  1283. else
  1284. {
  1285. continue;
  1286. }
  1287. if (midiEvent.size > 0)
  1288. pHost->write_midi_event(pHost->handle, &midiEvent);
  1289. }
  1290. }
  1291. }
  1292. // -------------------------------------------------------------------
  1293. // Plugin UI calls
  1294. void uiShow(const bool show)
  1295. {
  1296. if (show)
  1297. {
  1298. if (fUiServer.isPipeRunning())
  1299. {
  1300. fUiServer.writeFocusMessage();
  1301. return;
  1302. }
  1303. CarlaString path(pHost->resourceDir);
  1304. if (kIsPatchbay)
  1305. path += CARLA_OS_SEP_STR "carla-plugin-patchbay";
  1306. else
  1307. path += CARLA_OS_SEP_STR "carla-plugin";
  1308. #ifdef CARLA_OS_WIN
  1309. path += ".exe";
  1310. #endif
  1311. carla_stdout("Trying to start carla-plugin using \"%s\"", path.buffer());
  1312. fUiServer.setData(path, pData->sampleRate, pHost->uiName);
  1313. if (! fUiServer.startPipeServer(false))
  1314. {
  1315. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f);
  1316. return;
  1317. }
  1318. uiServerInfo();
  1319. uiServerOptions();
  1320. uiServerCallback(ENGINE_CALLBACK_ENGINE_STARTED, 0,
  1321. pData->options.processMode, pData->options.transportMode,
  1322. pData->sampleRate, "Plugin");
  1323. fUiServer.writeShowMessage();
  1324. for (uint i=0; i < pData->curPluginCount; ++i)
  1325. {
  1326. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1327. if (plugin != nullptr && plugin->isEnabled())
  1328. {
  1329. uiServerCallback(ENGINE_CALLBACK_PLUGIN_ADDED, i, 0, 0, 0.0f, plugin->getName());
  1330. }
  1331. }
  1332. if (kIsPatchbay)
  1333. patchbayRefresh(false);
  1334. if (fWaitForReadyMsg)
  1335. {
  1336. carla_stdout("Using Carla plugin embedded, waiting for it to be ready...");
  1337. for (; fUiServer.isPipeRunning() && ! fUiServer.isReady();)
  1338. {
  1339. carla_msleep(25);
  1340. fUiServer.idlePipe();
  1341. }
  1342. carla_stdout("Done!");
  1343. }
  1344. }
  1345. else
  1346. {
  1347. fUiServer.stopPipeServer(2000);
  1348. // hide all custom uis
  1349. for (uint i=0; i < pData->curPluginCount; ++i)
  1350. {
  1351. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1352. if (plugin != nullptr && plugin->isEnabled())
  1353. {
  1354. if (plugin->getHints() & PLUGIN_HAS_CUSTOM_UI)
  1355. {
  1356. try {
  1357. plugin->showCustomUI(false);
  1358. } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin showCustomUI (hide)");
  1359. }
  1360. }
  1361. }
  1362. }
  1363. }
  1364. void uiIdle()
  1365. {
  1366. for (uint i=0; i < pData->curPluginCount; ++i)
  1367. {
  1368. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1369. if (plugin != nullptr && plugin->isEnabled())
  1370. {
  1371. const uint hints(plugin->getHints());
  1372. if ((hints & PLUGIN_HAS_CUSTOM_UI) != 0 && (hints & PLUGIN_NEEDS_UI_MAIN_THREAD) != 0)
  1373. {
  1374. try {
  1375. plugin->uiIdle();
  1376. } CARLA_SAFE_EXCEPTION_CONTINUE("Plugin uiIdle");
  1377. }
  1378. }
  1379. }
  1380. idlePipe();
  1381. switch (fUiServer.getAndResetUiState())
  1382. {
  1383. case CarlaExternalUI::UiNone:
  1384. case CarlaExternalUI::UiShow:
  1385. break;
  1386. case CarlaExternalUI::UiCrashed:
  1387. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f);
  1388. break;
  1389. case CarlaExternalUI::UiHide:
  1390. pHost->ui_closed(pHost->handle);
  1391. fUiServer.stopPipeServer(1000);
  1392. break;
  1393. }
  1394. }
  1395. void idlePipe()
  1396. {
  1397. if (! fUiServer.isPipeRunning())
  1398. return;
  1399. fUiServer.idlePipe();
  1400. char tmpBuf[STR_MAX];
  1401. carla_zeroChars(tmpBuf, STR_MAX);
  1402. const CarlaMutexLocker cml(fUiServer.getPipeLock());
  1403. const ScopedLocale csl;
  1404. #ifndef CARLA_OS_WIN
  1405. const EngineTimeInfo& timeInfo(pData->timeInfo);
  1406. // send transport
  1407. if (! fUiServer.writeAndFixMessage("transport"))
  1408. return;
  1409. if (! fUiServer.writeMessage(timeInfo.playing ? "true\n" : "false\n"))
  1410. return;
  1411. if (timeInfo.bbt.valid)
  1412. {
  1413. std::sprintf(tmpBuf, P_UINT64 ":%i:%i:%i\n", timeInfo.frame, timeInfo.bbt.bar, timeInfo.bbt.beat, timeInfo.bbt.tick);
  1414. if (! fUiServer.writeMessage(tmpBuf))
  1415. return;
  1416. std::sprintf(tmpBuf, "%f\n", timeInfo.bbt.beatsPerMinute);
  1417. if (! fUiServer.writeMessage(tmpBuf))
  1418. return;
  1419. }
  1420. else
  1421. {
  1422. std::sprintf(tmpBuf, P_UINT64 ":0:0:0\n", timeInfo.frame);
  1423. if (! fUiServer.writeMessage(tmpBuf))
  1424. return;
  1425. if (! fUiServer.writeMessage("0.0\n"))
  1426. return;
  1427. }
  1428. fUiServer.flushMessages();
  1429. #endif
  1430. // send peaks and param outputs for all plugins
  1431. for (uint i=0; i < pData->curPluginCount; ++i)
  1432. {
  1433. const EnginePluginData& plugData(pData->plugins[i]);
  1434. const CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1435. std::sprintf(tmpBuf, "PEAKS_%i\n", i);
  1436. if (! fUiServer.writeMessage(tmpBuf))
  1437. return;
  1438. std::sprintf(tmpBuf, "%f:%f:%f:%f\n", plugData.insPeak[0], plugData.insPeak[1], plugData.outsPeak[0], plugData.outsPeak[1]);
  1439. if (! fUiServer.writeMessage(tmpBuf))
  1440. return;
  1441. fUiServer.flushMessages();
  1442. for (uint32_t j=0, count=plugin->getParameterCount(); j < count; ++j)
  1443. {
  1444. if (! plugin->isParameterOutput(j))
  1445. continue;
  1446. std::sprintf(tmpBuf, "PARAMVAL_%i:%i\n", i, j);
  1447. if (! fUiServer.writeMessage(tmpBuf))
  1448. return;
  1449. std::sprintf(tmpBuf, "%f\n", plugin->getParameterValue(j));
  1450. if (! fUiServer.writeMessage(tmpBuf))
  1451. return;
  1452. fUiServer.flushMessages();
  1453. }
  1454. }
  1455. }
  1456. // -------------------------------------------------------------------
  1457. // Plugin state calls
  1458. char* getState() const
  1459. {
  1460. MemoryOutputStream out;
  1461. saveProjectInternal(out);
  1462. return strdup(out.toString().toRawUTF8());
  1463. }
  1464. void setState(const char* const data)
  1465. {
  1466. // remove all plugins from UI side
  1467. for (uint i=0, count=pData->curPluginCount; i < count; ++i)
  1468. CarlaEngine::callback(ENGINE_CALLBACK_PLUGIN_REMOVED, count-i-1, 0, 0, 0.0f, nullptr);
  1469. // remove all plugins from backend, no lock
  1470. fIsRunning = false;
  1471. removeAllPlugins();
  1472. fIsRunning = true;
  1473. // stopped during removeAllPlugins()
  1474. if (! pData->thread.isThreadRunning())
  1475. pData->thread.startThread();
  1476. fOptionsForced = true;
  1477. const String state(data);
  1478. XmlDocument xml(state);
  1479. loadProjectInternal(xml);
  1480. }
  1481. // -------------------------------------------------------------------
  1482. public:
  1483. #define handlePtr ((CarlaEngineNative*)handle)
  1484. static NativePluginHandle _instantiateRack(const NativeHostDescriptor* host)
  1485. {
  1486. return new CarlaEngineNative(host, false, true);
  1487. }
  1488. static NativePluginHandle _instantiateRackNoMidiOut(const NativeHostDescriptor* host)
  1489. {
  1490. return new CarlaEngineNative(host, false, false);
  1491. }
  1492. static NativePluginHandle _instantiatePatchbay(const NativeHostDescriptor* host)
  1493. {
  1494. return new CarlaEngineNative(host, true, true);
  1495. }
  1496. static NativePluginHandle _instantiatePatchbay3s(const NativeHostDescriptor* host)
  1497. {
  1498. return new CarlaEngineNative(host, true, true, 3, 2);
  1499. }
  1500. static NativePluginHandle _instantiatePatchbay16(const NativeHostDescriptor* host)
  1501. {
  1502. return new CarlaEngineNative(host, true, true, 16, 16);
  1503. }
  1504. static NativePluginHandle _instantiatePatchbay32(const NativeHostDescriptor* host)
  1505. {
  1506. return new CarlaEngineNative(host, true, true, 32, 32);
  1507. }
  1508. static void _cleanup(NativePluginHandle handle)
  1509. {
  1510. delete handlePtr;
  1511. }
  1512. static uint32_t _get_parameter_count(NativePluginHandle handle)
  1513. {
  1514. return handlePtr->getParameterCount();
  1515. }
  1516. static const NativeParameter* _get_parameter_info(NativePluginHandle handle, uint32_t index)
  1517. {
  1518. return handlePtr->getParameterInfo(index);
  1519. }
  1520. static float _get_parameter_value(NativePluginHandle handle, uint32_t index)
  1521. {
  1522. return handlePtr->getParameterValue(index);
  1523. }
  1524. static uint32_t _get_midi_program_count(NativePluginHandle handle)
  1525. {
  1526. return handlePtr->getMidiProgramCount();
  1527. }
  1528. static const NativeMidiProgram* _get_midi_program_info(NativePluginHandle handle, uint32_t index)
  1529. {
  1530. return handlePtr->getMidiProgramInfo(index);
  1531. }
  1532. static void _set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  1533. {
  1534. handlePtr->setParameterValue(index, value);
  1535. }
  1536. static void _set_midi_program(NativePluginHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
  1537. {
  1538. handlePtr->setMidiProgram(channel, bank, program);
  1539. }
  1540. static void _ui_show(NativePluginHandle handle, bool show)
  1541. {
  1542. handlePtr->uiShow(show);
  1543. }
  1544. static void _ui_idle(NativePluginHandle handle)
  1545. {
  1546. handlePtr->uiIdle();
  1547. }
  1548. static void _activate(NativePluginHandle handle)
  1549. {
  1550. handlePtr->activate();
  1551. }
  1552. static void _deactivate(NativePluginHandle handle)
  1553. {
  1554. handlePtr->deactivate();
  1555. }
  1556. static void _process(NativePluginHandle handle, float** inBuffer, float** outBuffer, const uint32_t frames, const NativeMidiEvent* midiEvents, uint32_t midiEventCount)
  1557. {
  1558. handlePtr->process(inBuffer, outBuffer, frames, midiEvents, midiEventCount);
  1559. }
  1560. static char* _get_state(NativePluginHandle handle)
  1561. {
  1562. return handlePtr->getState();
  1563. }
  1564. static void _set_state(NativePluginHandle handle, const char* data)
  1565. {
  1566. handlePtr->setState(data);
  1567. }
  1568. static intptr_t _dispatcher(NativePluginHandle handle, NativePluginDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
  1569. {
  1570. switch(opcode)
  1571. {
  1572. case NATIVE_PLUGIN_OPCODE_NULL:
  1573. if (static_cast<uint32_t>(index) == 0xDEADF00D && static_cast<uintptr_t>(value) == 0xC0C0B00B)
  1574. {
  1575. handlePtr->fWaitForReadyMsg = true;
  1576. return handlePtr->fUiServer.getRemoteWinId();
  1577. }
  1578. return 0;
  1579. case NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
  1580. CARLA_SAFE_ASSERT_RETURN(value > 0, 0);
  1581. handlePtr->bufferSizeChanged(static_cast<uint32_t>(value));
  1582. return 0;
  1583. case NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
  1584. CARLA_SAFE_ASSERT_RETURN(opt > 0.0, 0);
  1585. handlePtr->sampleRateChanged(static_cast<double>(opt));
  1586. return 0;
  1587. case NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED:
  1588. handlePtr->offlineModeChanged(value != 0);
  1589. return 0;
  1590. case NATIVE_PLUGIN_OPCODE_UI_NAME_CHANGED:
  1591. //handlePtr->uiNameChanged(static_cast<const char*>(ptr));
  1592. return 0;
  1593. }
  1594. return 0;
  1595. // unused
  1596. (void)index;
  1597. (void)ptr;
  1598. }
  1599. // -------------------------------------------------------------------
  1600. static void _ui_server_callback(void* handle, EngineCallbackOpcode action, uint pluginId, int value1, int value2, float value3, const char* valueStr)
  1601. {
  1602. handlePtr->uiServerCallback(action, pluginId, value1, value2, value3, valueStr);
  1603. }
  1604. // -------------------------------------------------------------------
  1605. #undef handlePtr
  1606. private:
  1607. const NativeHostDescriptor* const pHost;
  1608. const bool kIsPatchbay; // rack if false
  1609. const bool kHasMidiOut;
  1610. bool fIsActive, fIsRunning;
  1611. CarlaEngineNativeUI fUiServer;
  1612. bool fOptionsForced;
  1613. bool fWaitForReadyMsg;
  1614. CarlaPlugin* _getFirstPlugin() const noexcept
  1615. {
  1616. if (pData->curPluginCount == 0 || pData->plugins == nullptr)
  1617. return nullptr;
  1618. CarlaPlugin* const plugin(pData->plugins[0].plugin);
  1619. if (plugin == nullptr || ! plugin->isEnabled())
  1620. return nullptr;
  1621. return pData->plugins[0].plugin;
  1622. }
  1623. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNative)
  1624. };
  1625. // -----------------------------------------------------------------------
  1626. static const NativePluginDescriptor carlaRackDesc = {
  1627. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  1628. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  1629. |NATIVE_PLUGIN_HAS_UI
  1630. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  1631. |NATIVE_PLUGIN_USES_STATE
  1632. |NATIVE_PLUGIN_USES_TIME),
  1633. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  1634. /* audioIns */ 2,
  1635. /* audioOuts */ 2,
  1636. /* midiIns */ 1,
  1637. /* midiOuts */ 1,
  1638. /* paramIns */ 0,
  1639. /* paramOuts */ 0,
  1640. /* name */ "Carla-Rack",
  1641. /* label */ "carlarack",
  1642. /* maker */ "falkTX",
  1643. /* copyright */ "GNU GPL v2+",
  1644. CarlaEngineNative::_instantiateRack,
  1645. CarlaEngineNative::_cleanup,
  1646. CarlaEngineNative::_get_parameter_count,
  1647. CarlaEngineNative::_get_parameter_info,
  1648. CarlaEngineNative::_get_parameter_value,
  1649. CarlaEngineNative::_get_midi_program_count,
  1650. CarlaEngineNative::_get_midi_program_info,
  1651. CarlaEngineNative::_set_parameter_value,
  1652. CarlaEngineNative::_set_midi_program,
  1653. /* _set_custom_data */ nullptr,
  1654. CarlaEngineNative::_ui_show,
  1655. CarlaEngineNative::_ui_idle,
  1656. /* _ui_set_parameter_value */ nullptr,
  1657. /* _ui_set_midi_program */ nullptr,
  1658. /* _ui_set_custom_data */ nullptr,
  1659. CarlaEngineNative::_activate,
  1660. CarlaEngineNative::_deactivate,
  1661. CarlaEngineNative::_process,
  1662. CarlaEngineNative::_get_state,
  1663. CarlaEngineNative::_set_state,
  1664. CarlaEngineNative::_dispatcher
  1665. };
  1666. static const NativePluginDescriptor carlaRackNoMidiOutDesc = {
  1667. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  1668. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  1669. |NATIVE_PLUGIN_HAS_UI
  1670. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  1671. |NATIVE_PLUGIN_USES_STATE
  1672. |NATIVE_PLUGIN_USES_TIME),
  1673. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  1674. /* audioIns */ 2,
  1675. /* audioOuts */ 2,
  1676. /* midiIns */ 1,
  1677. /* midiOuts */ 0,
  1678. /* paramIns */ 0,
  1679. /* paramOuts */ 0,
  1680. /* name */ "Carla-Rack (no midi out)",
  1681. /* label */ "carlarack-nomidiout",
  1682. /* maker */ "falkTX",
  1683. /* copyright */ "GNU GPL v2+",
  1684. CarlaEngineNative::_instantiateRackNoMidiOut,
  1685. CarlaEngineNative::_cleanup,
  1686. CarlaEngineNative::_get_parameter_count,
  1687. CarlaEngineNative::_get_parameter_info,
  1688. CarlaEngineNative::_get_parameter_value,
  1689. CarlaEngineNative::_get_midi_program_count,
  1690. CarlaEngineNative::_get_midi_program_info,
  1691. CarlaEngineNative::_set_parameter_value,
  1692. CarlaEngineNative::_set_midi_program,
  1693. /* _set_custom_data */ nullptr,
  1694. CarlaEngineNative::_ui_show,
  1695. CarlaEngineNative::_ui_idle,
  1696. /* _ui_set_parameter_value */ nullptr,
  1697. /* _ui_set_midi_program */ nullptr,
  1698. /* _ui_set_custom_data */ nullptr,
  1699. CarlaEngineNative::_activate,
  1700. CarlaEngineNative::_deactivate,
  1701. CarlaEngineNative::_process,
  1702. CarlaEngineNative::_get_state,
  1703. CarlaEngineNative::_set_state,
  1704. CarlaEngineNative::_dispatcher
  1705. };
  1706. static const NativePluginDescriptor carlaPatchbayDesc = {
  1707. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  1708. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  1709. |NATIVE_PLUGIN_HAS_UI
  1710. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  1711. |NATIVE_PLUGIN_USES_STATE
  1712. |NATIVE_PLUGIN_USES_TIME),
  1713. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  1714. /* audioIns */ 2,
  1715. /* audioOuts */ 2,
  1716. /* midiIns */ 1,
  1717. /* midiOuts */ 1,
  1718. /* paramIns */ 0,
  1719. /* paramOuts */ 0,
  1720. /* name */ "Carla-Patchbay",
  1721. /* label */ "carlapatchbay",
  1722. /* maker */ "falkTX",
  1723. /* copyright */ "GNU GPL v2+",
  1724. CarlaEngineNative::_instantiatePatchbay,
  1725. CarlaEngineNative::_cleanup,
  1726. CarlaEngineNative::_get_parameter_count,
  1727. CarlaEngineNative::_get_parameter_info,
  1728. CarlaEngineNative::_get_parameter_value,
  1729. CarlaEngineNative::_get_midi_program_count,
  1730. CarlaEngineNative::_get_midi_program_info,
  1731. CarlaEngineNative::_set_parameter_value,
  1732. CarlaEngineNative::_set_midi_program,
  1733. /* _set_custom_data */ nullptr,
  1734. CarlaEngineNative::_ui_show,
  1735. CarlaEngineNative::_ui_idle,
  1736. /* _ui_set_parameter_value */ nullptr,
  1737. /* _ui_set_midi_program */ nullptr,
  1738. /* _ui_set_custom_data */ nullptr,
  1739. CarlaEngineNative::_activate,
  1740. CarlaEngineNative::_deactivate,
  1741. CarlaEngineNative::_process,
  1742. CarlaEngineNative::_get_state,
  1743. CarlaEngineNative::_set_state,
  1744. CarlaEngineNative::_dispatcher
  1745. };
  1746. static const NativePluginDescriptor carlaPatchbay3sDesc = {
  1747. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  1748. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  1749. |NATIVE_PLUGIN_HAS_UI
  1750. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  1751. |NATIVE_PLUGIN_USES_STATE
  1752. |NATIVE_PLUGIN_USES_TIME),
  1753. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  1754. /* audioIns */ 3,
  1755. /* audioOuts */ 2,
  1756. /* midiIns */ 1,
  1757. /* midiOuts */ 1,
  1758. /* paramIns */ 0,
  1759. /* paramOuts */ 0,
  1760. /* name */ "Carla-Patchbay (sidechain)",
  1761. /* label */ "carlapatchbay3s",
  1762. /* maker */ "falkTX",
  1763. /* copyright */ "GNU GPL v2+",
  1764. CarlaEngineNative::_instantiatePatchbay3s,
  1765. CarlaEngineNative::_cleanup,
  1766. CarlaEngineNative::_get_parameter_count,
  1767. CarlaEngineNative::_get_parameter_info,
  1768. CarlaEngineNative::_get_parameter_value,
  1769. CarlaEngineNative::_get_midi_program_count,
  1770. CarlaEngineNative::_get_midi_program_info,
  1771. CarlaEngineNative::_set_parameter_value,
  1772. CarlaEngineNative::_set_midi_program,
  1773. /* _set_custom_data */ nullptr,
  1774. CarlaEngineNative::_ui_show,
  1775. CarlaEngineNative::_ui_idle,
  1776. /* _ui_set_parameter_value */ nullptr,
  1777. /* _ui_set_midi_program */ nullptr,
  1778. /* _ui_set_custom_data */ nullptr,
  1779. CarlaEngineNative::_activate,
  1780. CarlaEngineNative::_deactivate,
  1781. CarlaEngineNative::_process,
  1782. CarlaEngineNative::_get_state,
  1783. CarlaEngineNative::_set_state,
  1784. CarlaEngineNative::_dispatcher
  1785. };
  1786. static const NativePluginDescriptor carlaPatchbay16Desc = {
  1787. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  1788. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  1789. |NATIVE_PLUGIN_HAS_UI
  1790. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  1791. |NATIVE_PLUGIN_USES_STATE
  1792. |NATIVE_PLUGIN_USES_TIME),
  1793. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  1794. /* audioIns */ 16,
  1795. /* audioOuts */ 16,
  1796. /* midiIns */ 1,
  1797. /* midiOuts */ 1,
  1798. /* paramIns */ 0,
  1799. /* paramOuts */ 0,
  1800. /* name */ "Carla-Patchbay (16chan)",
  1801. /* label */ "carlapatchbay16",
  1802. /* maker */ "falkTX",
  1803. /* copyright */ "GNU GPL v2+",
  1804. CarlaEngineNative::_instantiatePatchbay16,
  1805. CarlaEngineNative::_cleanup,
  1806. CarlaEngineNative::_get_parameter_count,
  1807. CarlaEngineNative::_get_parameter_info,
  1808. CarlaEngineNative::_get_parameter_value,
  1809. CarlaEngineNative::_get_midi_program_count,
  1810. CarlaEngineNative::_get_midi_program_info,
  1811. CarlaEngineNative::_set_parameter_value,
  1812. CarlaEngineNative::_set_midi_program,
  1813. /* _set_custom_data */ nullptr,
  1814. CarlaEngineNative::_ui_show,
  1815. CarlaEngineNative::_ui_idle,
  1816. /* _ui_set_parameter_value */ nullptr,
  1817. /* _ui_set_midi_program */ nullptr,
  1818. /* _ui_set_custom_data */ nullptr,
  1819. CarlaEngineNative::_activate,
  1820. CarlaEngineNative::_deactivate,
  1821. CarlaEngineNative::_process,
  1822. CarlaEngineNative::_get_state,
  1823. CarlaEngineNative::_set_state,
  1824. CarlaEngineNative::_dispatcher
  1825. };
  1826. static const NativePluginDescriptor carlaPatchbay32Desc = {
  1827. /* category */ NATIVE_PLUGIN_CATEGORY_OTHER,
  1828. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  1829. |NATIVE_PLUGIN_HAS_UI
  1830. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  1831. |NATIVE_PLUGIN_USES_STATE
  1832. |NATIVE_PLUGIN_USES_TIME),
  1833. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_EVERYTHING),
  1834. /* audioIns */ 32,
  1835. /* audioOuts */ 32,
  1836. /* midiIns */ 1,
  1837. /* midiOuts */ 1,
  1838. /* paramIns */ 0,
  1839. /* paramOuts */ 0,
  1840. /* name */ "Carla-Patchbay (32chan)",
  1841. /* label */ "carlapatchbay32",
  1842. /* maker */ "falkTX",
  1843. /* copyright */ "GNU GPL v2+",
  1844. CarlaEngineNative::_instantiatePatchbay32,
  1845. CarlaEngineNative::_cleanup,
  1846. CarlaEngineNative::_get_parameter_count,
  1847. CarlaEngineNative::_get_parameter_info,
  1848. CarlaEngineNative::_get_parameter_value,
  1849. CarlaEngineNative::_get_midi_program_count,
  1850. CarlaEngineNative::_get_midi_program_info,
  1851. CarlaEngineNative::_set_parameter_value,
  1852. CarlaEngineNative::_set_midi_program,
  1853. /* _set_custom_data */ nullptr,
  1854. CarlaEngineNative::_ui_show,
  1855. CarlaEngineNative::_ui_idle,
  1856. /* _ui_set_parameter_value */ nullptr,
  1857. /* _ui_set_midi_program */ nullptr,
  1858. /* _ui_set_custom_data */ nullptr,
  1859. CarlaEngineNative::_activate,
  1860. CarlaEngineNative::_deactivate,
  1861. CarlaEngineNative::_process,
  1862. CarlaEngineNative::_get_state,
  1863. CarlaEngineNative::_set_state,
  1864. CarlaEngineNative::_dispatcher
  1865. };
  1866. CARLA_BACKEND_END_NAMESPACE
  1867. // -----------------------------------------------------------------------
  1868. CARLA_EXPORT
  1869. void carla_register_native_plugin_carla();
  1870. void carla_register_native_plugin_carla()
  1871. {
  1872. CARLA_BACKEND_USE_NAMESPACE;
  1873. carla_register_native_plugin(&carlaRackDesc);
  1874. carla_register_native_plugin(&carlaRackNoMidiOutDesc);
  1875. carla_register_native_plugin(&carlaPatchbayDesc);
  1876. carla_register_native_plugin(&carlaPatchbay3sDesc);
  1877. carla_register_native_plugin(&carlaPatchbay16Desc);
  1878. carla_register_native_plugin(&carlaPatchbay32Desc);
  1879. }
  1880. // -----------------------------------------------------------------------
  1881. CARLA_EXPORT
  1882. const NativePluginDescriptor* carla_get_native_rack_plugin();
  1883. const NativePluginDescriptor* carla_get_native_rack_plugin()
  1884. {
  1885. CARLA_BACKEND_USE_NAMESPACE;
  1886. return &carlaRackDesc;
  1887. }
  1888. CARLA_EXPORT
  1889. const NativePluginDescriptor* carla_get_native_patchbay_plugin();
  1890. const NativePluginDescriptor* carla_get_native_patchbay_plugin()
  1891. {
  1892. CARLA_BACKEND_USE_NAMESPACE;
  1893. return &carlaPatchbayDesc;
  1894. }
  1895. // -----------------------------------------------------------------------
  1896. // Extra stuff for linking purposes
  1897. #ifdef CARLA_PLUGIN_EXPORT
  1898. CARLA_BACKEND_START_NAMESPACE
  1899. CarlaEngine* CarlaEngine::newJack() { return nullptr; }
  1900. CarlaEngine* CarlaEngine::newRtAudio(const AudioApi) { return nullptr; }
  1901. uint CarlaEngine::getRtAudioApiCount() { return 0; }
  1902. const char* CarlaEngine::getRtAudioApiName(const uint) { return nullptr; }
  1903. const char* const* CarlaEngine::getRtAudioApiDeviceNames(const uint) { return nullptr; }
  1904. const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const uint, const char* const) { return nullptr; }
  1905. CARLA_BACKEND_END_NAMESPACE
  1906. #define CARLA_PLUGIN_UI_CLASS_PREFIX EngineNative
  1907. #include "CarlaHostCommon.cpp"
  1908. #include "CarlaPluginUI.cpp"
  1909. #include "CarlaDssiUtils.cpp"
  1910. #include "CarlaPatchbayUtils.cpp"
  1911. #include "CarlaPipeUtils.cpp"
  1912. #include "CarlaStateUtils.cpp"
  1913. #endif
  1914. // -----------------------------------------------------------------------