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

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