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

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642
  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaDefines.h"
  18. #ifdef BUILD_BRIDGE
  19. # error This file should not be compiled if building bridge
  20. #endif
  21. #ifdef CARLA_OS_WIN
  22. # error This file should not be compiled for Windows
  23. #endif
  24. #include "CarlaEngineInternal.hpp"
  25. #include "CarlaPlugin.hpp"
  26. #include "CarlaBackendUtils.hpp"
  27. #include "CarlaMathUtils.hpp"
  28. #include "CarlaStateUtils.hpp"
  29. #include "CarlaExternalUI.hpp"
  30. #include "CarlaNative.hpp"
  31. #include <QtCore/QTextStream>
  32. #include <QtXml/QDomNode>
  33. CARLA_BACKEND_START_NAMESPACE
  34. #if 0
  35. } // Fix editor indentation
  36. #endif
  37. // -----------------------------------------------------------------------
  38. class CarlaEngineNativeUI : public CarlaExternalUI
  39. {
  40. public:
  41. CarlaEngineNativeUI(CarlaEngine* const engine)
  42. : fEngine(engine)
  43. {
  44. carla_debug("CarlaEngineNativeUI::CarlaEngineNativeUI(%p)", engine);
  45. }
  46. ~CarlaEngineNativeUI() override
  47. {
  48. carla_debug("CarlaEngineNativeUI::~CarlaEngineNativeUI()");
  49. }
  50. protected:
  51. bool msgReceived(const char* const msg) noexcept override
  52. {
  53. if (CarlaExternalUI::msgReceived(msg))
  54. return true;
  55. bool ok = true;
  56. if (std::strcmp(msg, "set_engine_option") == 0)
  57. {
  58. uint32_t option;
  59. int32_t value;
  60. const char* valueStr;
  61. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(option), true);
  62. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(value), true);
  63. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(valueStr), true);
  64. try {
  65. fEngine->setOption(static_cast<EngineOption>(option), value, valueStr);
  66. } catch(...) {}
  67. delete[] valueStr;
  68. }
  69. else if (std::strcmp(msg, "load_file") == 0)
  70. {
  71. const char* filename;
  72. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename), true);
  73. try {
  74. ok = fEngine->loadFile(filename);
  75. } catch(...) {}
  76. delete[] filename;
  77. }
  78. else if (std::strcmp(msg, "load_project") == 0)
  79. {
  80. const char* filename;
  81. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename), true);
  82. try {
  83. ok = fEngine->loadProject(filename);
  84. } catch(...) {}
  85. delete[] filename;
  86. }
  87. else if (std::strcmp(msg, "save_project") == 0)
  88. {
  89. const char* filename;
  90. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename), true);
  91. try {
  92. ok = fEngine->saveProject(filename);
  93. } catch(...) {}
  94. delete[] filename;
  95. }
  96. else if (std::strcmp(msg, "patchbay_connect") == 0)
  97. {
  98. int32_t groupA, portA, groupB, portB;
  99. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(groupA), true);
  100. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(portA), true);
  101. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(groupB), true);
  102. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(portB), true);
  103. try {
  104. ok = fEngine->patchbayConnect(groupA, portA, groupB, portB);
  105. } catch(...) {}
  106. }
  107. else if (std::strcmp(msg, "patchbay_disconnect") == 0)
  108. {
  109. uint32_t connectionId;
  110. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(connectionId), true);
  111. try {
  112. ok = fEngine->patchbayDisconnect(connectionId);
  113. } catch(...) {}
  114. }
  115. else if (std::strcmp(msg, "patchbay_refresh") == 0)
  116. {
  117. try {
  118. ok = fEngine->patchbayRefresh();
  119. } catch(...) {}
  120. }
  121. else if (std::strcmp(msg, "transport_play") == 0)
  122. {
  123. fEngine->transportPlay();
  124. }
  125. else if (std::strcmp(msg, "transport_pause") == 0)
  126. {
  127. fEngine->transportPause();
  128. }
  129. else if (std::strcmp(msg, "transport_relocate") == 0)
  130. {
  131. uint64_t frame;
  132. CARLA_SAFE_ASSERT_RETURN(readNextLineAsULong(frame), true);
  133. fEngine->transportRelocate(frame);
  134. }
  135. else if (std::strcmp(msg, "add_plugin") == 0)
  136. {
  137. uint32_t btype, ptype;
  138. const char* filename = nullptr;
  139. const char* name;
  140. const char* label;
  141. int64_t uniqueId;
  142. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(btype), true);
  143. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(ptype), true);
  144. readNextLineAsString(filename); // can be null
  145. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(name), true);
  146. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(label), true);
  147. CARLA_SAFE_ASSERT_RETURN(readNextLineAsLong(uniqueId), true);
  148. if (filename != nullptr && std::strcmp(filename, "(null)") == 0)
  149. {
  150. delete[] filename;
  151. filename = nullptr;
  152. }
  153. if (std::strcmp(name, "(null)") == 0)
  154. {
  155. delete[] name;
  156. name = nullptr;
  157. }
  158. ok = fEngine->addPlugin(static_cast<BinaryType>(btype), static_cast<PluginType>(ptype), filename, name, label, uniqueId, nullptr);
  159. if (filename != nullptr)
  160. delete[] filename;
  161. if (name != nullptr)
  162. delete[] name;
  163. delete[] label;
  164. }
  165. else if (std::strcmp(msg, "remove_plugin") == 0)
  166. {
  167. uint32_t pluginId;
  168. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  169. ok = fEngine->removePlugin(pluginId);
  170. }
  171. else if (std::strcmp(msg, "remove_all_plugins") == 0)
  172. {
  173. ok = fEngine->removeAllPlugins();
  174. }
  175. else if (std::strcmp(msg, "rename_plugin") == 0)
  176. {
  177. uint32_t pluginId;
  178. const char* newName;
  179. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  180. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(newName), true);
  181. // TODO
  182. /*const char* name =*/ fEngine->renamePlugin(pluginId, newName);
  183. delete[] newName;
  184. }
  185. else if (std::strcmp(msg, "clone_plugin") == 0)
  186. {
  187. uint32_t pluginId;
  188. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  189. ok = fEngine->clonePlugin(pluginId);
  190. }
  191. else if (std::strcmp(msg, "replace_plugin") == 0)
  192. {
  193. uint32_t pluginId;
  194. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  195. ok = fEngine->replacePlugin(pluginId);
  196. }
  197. else if (std::strcmp(msg, "switch_plugins") == 0)
  198. {
  199. uint32_t pluginIdA, pluginIdB;
  200. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginIdA), true);
  201. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginIdB), true);
  202. ok = fEngine->switchPlugins(pluginIdA, pluginIdB);
  203. }
  204. else if (std::strcmp(msg, "load_plugin_state") == 0)
  205. {
  206. uint32_t pluginId;
  207. const char* filename;
  208. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  209. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename), true);
  210. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  211. plugin->loadStateFromFile(filename);
  212. delete[] filename;
  213. }
  214. else if (std::strcmp(msg, "save_plugin_state") == 0)
  215. {
  216. uint32_t pluginId;
  217. const char* filename;
  218. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  219. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename), true);
  220. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  221. plugin->saveStateToFile(filename);
  222. delete[] filename;
  223. }
  224. else if (std::strcmp(msg, "set_option") == 0)
  225. {
  226. uint32_t pluginId, option;
  227. bool yesNo;
  228. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  229. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(option), true);
  230. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo), true);
  231. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  232. plugin->setOption(option, yesNo);
  233. }
  234. else if (std::strcmp(msg, "set_active") == 0)
  235. {
  236. uint32_t pluginId;
  237. bool onOff;
  238. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  239. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(onOff), true);
  240. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  241. plugin->setActive(onOff, true, false);
  242. }
  243. else if (std::strcmp(msg, "set_drywet") == 0)
  244. {
  245. uint32_t pluginId;
  246. float value;
  247. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  248. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  249. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  250. plugin->setDryWet(value, true, false);
  251. }
  252. else if (std::strcmp(msg, "set_volume") == 0)
  253. {
  254. uint32_t pluginId;
  255. float value;
  256. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  257. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  258. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  259. plugin->setVolume(value, true, false);
  260. }
  261. else if (std::strcmp(msg, "set_balance_left") == 0)
  262. {
  263. uint32_t pluginId;
  264. float value;
  265. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  266. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  267. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  268. plugin->setBalanceLeft(value, true, false);
  269. }
  270. else if (std::strcmp(msg, "set_balance_right") == 0)
  271. {
  272. uint32_t pluginId;
  273. float value;
  274. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  275. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  276. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  277. plugin->setBalanceRight(value, true, false);
  278. }
  279. else if (std::strcmp(msg, "set_panning") == 0)
  280. {
  281. uint32_t pluginId;
  282. float value;
  283. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  284. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  285. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  286. plugin->setPanning(value, true, false);
  287. }
  288. else if (std::strcmp(msg, "set_ctrl_channel") == 0)
  289. {
  290. uint32_t pluginId;
  291. int32_t channel;
  292. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  293. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(channel), true);
  294. CARLA_SAFE_ASSERT_RETURN(channel >= -1 && channel < MAX_MIDI_CHANNELS, true);
  295. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  296. plugin->setCtrlChannel(int8_t(channel), true, false);
  297. }
  298. else if (std::strcmp(msg, "set_parameter_value") == 0)
  299. {
  300. uint32_t pluginId, parameterId;
  301. float value;
  302. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  303. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
  304. CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
  305. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  306. plugin->setParameterValue(parameterId, value, true, true, false);
  307. }
  308. else if (std::strcmp(msg, "set_parameter_midi_channel") == 0)
  309. {
  310. uint32_t pluginId, parameterId, channel;
  311. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  312. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
  313. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(channel), true);
  314. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, true);
  315. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  316. plugin->setParameterMidiChannel(parameterId, static_cast<uint8_t>(channel), true, false);
  317. }
  318. else if (std::strcmp(msg, "set_parameter_midi_cc") == 0)
  319. {
  320. uint32_t pluginId, parameterId;
  321. int32_t cc;
  322. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  323. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
  324. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(cc), true);
  325. CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < 0x5F, true);
  326. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  327. plugin->setParameterMidiCC(parameterId, static_cast<int16_t>(cc), true, false);
  328. }
  329. else if (std::strcmp(msg, "set_program") == 0)
  330. {
  331. uint32_t pluginId;
  332. int32_t index;
  333. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  334. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index), true);
  335. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  336. plugin->setProgram(index, true, true, false);
  337. }
  338. else if (std::strcmp(msg, "set_midi_program") == 0)
  339. {
  340. uint32_t pluginId;
  341. int32_t index;
  342. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  343. CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index), true);
  344. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  345. plugin->setMidiProgram(index, true, true, false);
  346. }
  347. else if (std::strcmp(msg, "set_custom_data") == 0)
  348. {
  349. uint32_t pluginId;
  350. const char* type;
  351. const char* key;
  352. const char* value;
  353. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  354. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(type), true);
  355. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(key), true);
  356. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(value), true);
  357. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  358. plugin->setCustomData(type, key, value, true);
  359. delete[] type;
  360. delete[] key;
  361. delete[] value;
  362. }
  363. else if (std::strcmp(msg, "set_chunk_data") == 0)
  364. {
  365. uint32_t pluginId;
  366. const char* cdata;
  367. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  368. CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(cdata), true);
  369. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  370. plugin->setChunkData(cdata);
  371. delete[] cdata;
  372. }
  373. else if (std::strcmp(msg, "prepare_for_save") == 0)
  374. {
  375. uint32_t pluginId;
  376. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  377. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  378. plugin->prepareForSave();
  379. }
  380. else if (std::strcmp(msg, "randomize_parameters") == 0)
  381. {
  382. uint32_t pluginId;
  383. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  384. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  385. plugin->randomizeParameters();
  386. }
  387. else if (std::strcmp(msg, "send_midi_note") == 0)
  388. {
  389. uint32_t pluginId, channel, note, velocity;
  390. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  391. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(channel), true);
  392. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(note), true);
  393. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(velocity), true);
  394. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, true);
  395. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_VALUE, true);
  396. CARLA_SAFE_ASSERT_RETURN(velocity < MAX_MIDI_VALUE, true);
  397. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  398. plugin->sendMidiSingleNote(static_cast<uint8_t>(channel), static_cast<uint8_t>(note), static_cast<uint8_t>(velocity), true, true, false);
  399. }
  400. else if (std::strcmp(msg, "show_custom_ui") == 0)
  401. {
  402. uint32_t pluginId;
  403. bool yesNo;
  404. CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
  405. CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo), true);
  406. if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
  407. plugin->showCustomUI(yesNo);
  408. }
  409. else
  410. {
  411. carla_stderr("msgReceived : %s", msg);
  412. return false;
  413. }
  414. if (! ok)
  415. {
  416. writeMsg("error\n", 6);
  417. writeAndFixMsg(fEngine->getLastError());
  418. }
  419. return true;
  420. }
  421. private:
  422. CarlaEngine* const fEngine;
  423. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNativeUI)
  424. };
  425. // -----------------------------------------------------------------------
  426. class CarlaEngineNative : public CarlaEngine
  427. {
  428. public:
  429. CarlaEngineNative(const NativeHostDescriptor* const host, const bool isPatchbay)
  430. : CarlaEngine(),
  431. pHost(host),
  432. fIsPatchbay(isPatchbay),
  433. fIsActive(false),
  434. fIsRunning(false),
  435. fUiServer(this)
  436. {
  437. carla_debug("CarlaEngineNative::CarlaEngineNative()");
  438. carla_zeroChar(fTmpBuf, STR_MAX+1);
  439. // set-up engine
  440. if (fIsPatchbay)
  441. {
  442. pData->options.processMode = ENGINE_PROCESS_MODE_PATCHBAY;
  443. pData->options.transportMode = ENGINE_TRANSPORT_MODE_PLUGIN;
  444. pData->options.forceStereo = false;
  445. pData->options.preferPluginBridges = false;
  446. pData->options.preferUiBridges = false;
  447. init("Carla-Patchbay");
  448. }
  449. else
  450. {
  451. pData->options.processMode = ENGINE_PROCESS_MODE_CONTINUOUS_RACK;
  452. pData->options.transportMode = ENGINE_TRANSPORT_MODE_PLUGIN;
  453. pData->options.forceStereo = true;
  454. pData->options.preferPluginBridges = false;
  455. pData->options.preferUiBridges = false;
  456. init("Carla-Rack");
  457. }
  458. if (pData->options.resourceDir != nullptr)
  459. delete[] pData->options.resourceDir;
  460. if (pData->options.binaryDir != nullptr)
  461. delete[] pData->options.binaryDir;
  462. pData->options.resourceDir = carla_strdup(pHost->resourceDir);
  463. pData->options.binaryDir = carla_strdup(pHost->resourceDir);
  464. setCallback(_ui_server_callback, this);
  465. }
  466. ~CarlaEngineNative() override
  467. {
  468. CARLA_SAFE_ASSERT(! fIsActive);
  469. carla_debug("CarlaEngineNative::~CarlaEngineNative() - START");
  470. pData->aboutToClose = true;
  471. fIsRunning = false;
  472. removeAllPlugins();
  473. runPendingRtEvents();
  474. close();
  475. carla_debug("CarlaEngineNative::~CarlaEngineNative() - END");
  476. }
  477. protected:
  478. // -------------------------------------
  479. // CarlaEngine virtual calls
  480. bool init(const char* const clientName) override
  481. {
  482. carla_debug("CarlaEngineNative::init(\"%s\")", clientName);
  483. pData->bufferSize = pHost->get_buffer_size(pHost->handle);
  484. pData->sampleRate = pHost->get_sample_rate(pHost->handle);
  485. fIsRunning = true;
  486. CarlaEngine::init(clientName);
  487. return true;
  488. }
  489. bool isRunning() const noexcept override
  490. {
  491. return fIsRunning;
  492. }
  493. bool isOffline() const noexcept override
  494. {
  495. return pHost->is_offline(pHost->handle);
  496. }
  497. EngineType getType() const noexcept override
  498. {
  499. return kEngineTypePlugin;
  500. }
  501. const char* getCurrentDriverName() const noexcept override
  502. {
  503. return "Plugin";
  504. }
  505. // -------------------------------------------------------------------
  506. const char* renamePlugin(const unsigned int id, const char* const newName) override
  507. {
  508. if (const char* const retName = CarlaEngine::renamePlugin(id, newName))
  509. {
  510. uiServerCallback(ENGINE_CALLBACK_PLUGIN_RENAMED, id, 0, 0, 0.0f, retName);
  511. return retName;
  512. }
  513. return nullptr;
  514. }
  515. // -------------------------------------------------------------------
  516. void bufferSizeChanged(const uint32_t newBufferSize)
  517. {
  518. pData->bufferSize = newBufferSize;
  519. CarlaEngine::bufferSizeChanged(newBufferSize);
  520. }
  521. void sampleRateChanged(const double newSampleRate)
  522. {
  523. pData->sampleRate = newSampleRate;
  524. CarlaEngine::sampleRateChanged(newSampleRate);
  525. }
  526. // -------------------------------------------------------------------
  527. void uiServerSendPluginInfo(CarlaPlugin* const plugin)
  528. {
  529. const uint pluginId(plugin->getId());
  530. std::sprintf(fTmpBuf, "PLUGIN_INFO_%i\n", pluginId);
  531. fUiServer.writeMsg(fTmpBuf);
  532. std::sprintf(fTmpBuf, "%i:%i:%i:" P_INT64 ":%i:%i\n", plugin->getType(), plugin->getCategory(), plugin->getHints(), plugin->getUniqueId(), plugin->getOptionsAvailable(), plugin->getOptionsEnabled());
  533. fUiServer.writeMsg(fTmpBuf);
  534. if (const char* const filename = plugin->getFilename())
  535. {
  536. std::sprintf(fTmpBuf, "%s", filename);
  537. fUiServer.writeAndFixMsg(fTmpBuf);
  538. }
  539. else
  540. fUiServer.writeMsg("\n");
  541. if (const char* const name = plugin->getName())
  542. {
  543. std::sprintf(fTmpBuf, "%s", name);
  544. fUiServer.writeAndFixMsg(fTmpBuf);
  545. }
  546. else
  547. fUiServer.writeMsg("\n");
  548. if (const char* const iconName = plugin->getIconName())
  549. {
  550. std::sprintf(fTmpBuf, "%s", iconName);
  551. fUiServer.writeAndFixMsg(fTmpBuf);
  552. }
  553. else
  554. fUiServer.writeMsg("\n");
  555. plugin->getRealName(fTmpBuf);
  556. fUiServer.writeAndFixMsg(fTmpBuf);
  557. plugin->getLabel(fTmpBuf);
  558. fUiServer.writeAndFixMsg(fTmpBuf);
  559. plugin->getMaker(fTmpBuf);
  560. fUiServer.writeAndFixMsg(fTmpBuf);
  561. plugin->getCopyright(fTmpBuf);
  562. fUiServer.writeAndFixMsg(fTmpBuf);
  563. std::sprintf(fTmpBuf, "AUDIO_COUNT_%i:%i:%i\n", pluginId, plugin->getAudioInCount(), plugin->getAudioOutCount());
  564. fUiServer.writeMsg(fTmpBuf);
  565. std::sprintf(fTmpBuf, "MIDI_COUNT_%i:%i:%i\n", pluginId, plugin->getMidiInCount(), plugin->getMidiOutCount());
  566. fUiServer.writeMsg(fTmpBuf);
  567. }
  568. void uiServerSendPluginParameters(CarlaPlugin* const plugin)
  569. {
  570. const uint pluginId(plugin->getId());
  571. uint32_t ins, outs, count;
  572. plugin->getParameterCountInfo(ins, outs);
  573. count = plugin->getParameterCount();
  574. std::sprintf(fTmpBuf, "PARAMETER_COUNT_%i:%i:%i:%i\n", pluginId, ins, outs, count);
  575. fUiServer.writeMsg(fTmpBuf);
  576. for (uint32_t i=0; i<count; ++i)
  577. {
  578. const ParameterData& paramData(plugin->getParameterData(i));
  579. const ParameterRanges& paramRanges(plugin->getParameterRanges(i));
  580. std::sprintf(fTmpBuf, "PARAMETER_DATA_%i:%i\n", pluginId, i);
  581. fUiServer.writeMsg(fTmpBuf);
  582. std::sprintf(fTmpBuf, "%i:%i:%i:%i\n", paramData.type, paramData.hints, paramData.midiChannel, paramData.midiCC);
  583. fUiServer.writeMsg(fTmpBuf);
  584. plugin->getParameterName(i, fTmpBuf);
  585. fUiServer.writeAndFixMsg(fTmpBuf);
  586. plugin->getParameterUnit(i, fTmpBuf);
  587. fUiServer.writeAndFixMsg(fTmpBuf);
  588. std::sprintf(fTmpBuf, "PARAMETER_RANGES_%i:%i\n", pluginId, i);
  589. fUiServer.writeMsg(fTmpBuf);
  590. std::sprintf(fTmpBuf, "%f:%f:%f:%f:%f:%f\n", paramRanges.def, paramRanges.min, paramRanges.max, paramRanges.step, paramRanges.stepSmall, paramRanges.stepLarge);
  591. fUiServer.writeMsg(fTmpBuf);
  592. std::sprintf(fTmpBuf, "PARAMVAL_%i:%i\n", pluginId, i);
  593. fUiServer.writeMsg(fTmpBuf);
  594. std::sprintf(fTmpBuf, "%f\n", plugin->getParameterValue(i));
  595. fUiServer.writeMsg(fTmpBuf);
  596. }
  597. }
  598. void uiServerSendPluginPrograms(CarlaPlugin* const plugin)
  599. {
  600. const uint pluginId(plugin->getId());
  601. uint32_t count = plugin->getProgramCount();
  602. std::sprintf(fTmpBuf, "PROGRAM_COUNT_%i:%i:%i\n", pluginId, count, plugin->getCurrentProgram());
  603. fUiServer.writeMsg(fTmpBuf);
  604. for (uint32_t i=0; i<count; ++i)
  605. {
  606. std::sprintf(fTmpBuf, "PROGRAM_NAME_%i:%i\n", pluginId, i);
  607. fUiServer.writeMsg(fTmpBuf);
  608. plugin->getProgramName(i, fTmpBuf);
  609. fUiServer.writeAndFixMsg(fTmpBuf);
  610. }
  611. count = plugin->getMidiProgramCount();
  612. std::sprintf(fTmpBuf, "MIDI_PROGRAM_COUNT_%i:%i:%i\n", pluginId, count, plugin->getCurrentMidiProgram());
  613. fUiServer.writeMsg(fTmpBuf);
  614. for (uint32_t i=0; i<count; ++i)
  615. {
  616. std::sprintf(fTmpBuf, "MIDI_PROGRAM_DATA_%i:%i\n", pluginId, i);
  617. fUiServer.writeMsg(fTmpBuf);
  618. const MidiProgramData& mpData(plugin->getMidiProgramData(i));
  619. std::sprintf(fTmpBuf, "%i:%i\n", mpData.bank, mpData.program);
  620. fUiServer.writeMsg(fTmpBuf);
  621. std::sprintf(fTmpBuf, "%s", mpData.name);
  622. fUiServer.writeAndFixMsg(fTmpBuf);
  623. }
  624. }
  625. void uiServerCallback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const float value3, const char* const valueStr)
  626. {
  627. if (! fIsRunning)
  628. return;
  629. if (! fUiServer.isOk())
  630. return;
  631. CarlaPlugin* plugin;
  632. switch (action)
  633. {
  634. case ENGINE_CALLBACK_RELOAD_INFO:
  635. plugin = getPlugin(pluginId);
  636. if (plugin != nullptr && plugin->isEnabled())
  637. {
  638. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  639. uiServerSendPluginInfo(plugin);
  640. }
  641. break;
  642. case ENGINE_CALLBACK_RELOAD_PARAMETERS:
  643. plugin = getPlugin(pluginId);
  644. if (plugin != nullptr && plugin->isEnabled())
  645. {
  646. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  647. uiServerSendPluginParameters(plugin);
  648. }
  649. break;
  650. case ENGINE_CALLBACK_RELOAD_PROGRAMS:
  651. plugin = getPlugin(pluginId);
  652. if (plugin != nullptr && plugin->isEnabled())
  653. {
  654. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  655. uiServerSendPluginPrograms(plugin);
  656. }
  657. break;
  658. case ENGINE_CALLBACK_RELOAD_ALL:
  659. case ENGINE_CALLBACK_PLUGIN_ADDED:
  660. plugin = getPlugin(pluginId);
  661. if (plugin != nullptr && plugin->isEnabled())
  662. {
  663. CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId);
  664. uiServerSendPluginInfo(plugin);
  665. uiServerSendPluginParameters(plugin);
  666. uiServerSendPluginPrograms(plugin);
  667. }
  668. break;
  669. default:
  670. break;
  671. }
  672. std::sprintf(fTmpBuf, "ENGINE_CALLBACK_%i\n", int(action));
  673. fUiServer.writeMsg(fTmpBuf);
  674. std::sprintf(fTmpBuf, "%u\n", pluginId);
  675. fUiServer.writeMsg(fTmpBuf);
  676. std::sprintf(fTmpBuf, "%i\n", value1);
  677. fUiServer.writeMsg(fTmpBuf);
  678. std::sprintf(fTmpBuf, "%i\n", value2);
  679. fUiServer.writeMsg(fTmpBuf);
  680. std::sprintf(fTmpBuf, "%f\n", value3);
  681. fUiServer.writeMsg(fTmpBuf);
  682. fUiServer.writeAndFixMsg(valueStr);
  683. }
  684. // -------------------------------------------------------------------
  685. // Plugin parameter calls
  686. uint32_t getParameterCount() const
  687. {
  688. if (CarlaPlugin* const plugin = _getFirstPlugin())
  689. return plugin->getParameterCount();
  690. return 0;
  691. }
  692. const NativeParameter* getParameterInfo(const uint32_t index) const
  693. {
  694. if (CarlaPlugin* const plugin = _getFirstPlugin())
  695. {
  696. if (index < plugin->getParameterCount())
  697. {
  698. static NativeParameter param;
  699. static char strBufName[STR_MAX+1];
  700. static char strBufUnit[STR_MAX+1];
  701. const ParameterData& paramData(plugin->getParameterData(index));
  702. const ParameterRanges& paramRanges(plugin->getParameterRanges(index));
  703. plugin->getParameterName(index, strBufName);
  704. plugin->getParameterUnit(index, strBufUnit);
  705. unsigned int hints = 0x0;
  706. if (paramData.hints & PARAMETER_IS_BOOLEAN)
  707. hints |= ::PARAMETER_IS_BOOLEAN;
  708. if (paramData.hints & PARAMETER_IS_INTEGER)
  709. hints |= ::PARAMETER_IS_INTEGER;
  710. if (paramData.hints & PARAMETER_IS_LOGARITHMIC)
  711. hints |= ::PARAMETER_IS_LOGARITHMIC;
  712. if (paramData.hints & PARAMETER_IS_AUTOMABLE)
  713. hints |= ::PARAMETER_IS_AUTOMABLE;
  714. if (paramData.hints & PARAMETER_USES_SAMPLERATE)
  715. hints |= ::PARAMETER_USES_SAMPLE_RATE;
  716. if (paramData.hints & PARAMETER_USES_SCALEPOINTS)
  717. hints |= ::PARAMETER_USES_SCALEPOINTS;
  718. if (paramData.hints & PARAMETER_USES_CUSTOM_TEXT)
  719. hints |= ::PARAMETER_USES_CUSTOM_TEXT;
  720. if (paramData.type == PARAMETER_INPUT || paramData.type == PARAMETER_OUTPUT)
  721. {
  722. if (paramData.hints & PARAMETER_IS_ENABLED)
  723. hints |= ::PARAMETER_IS_ENABLED;
  724. if (paramData.type == PARAMETER_OUTPUT)
  725. hints |= ::PARAMETER_IS_OUTPUT;
  726. }
  727. param.hints = static_cast<NativeParameterHints>(hints);
  728. param.name = strBufName;
  729. param.unit = strBufUnit;
  730. param.ranges.def = paramRanges.def;
  731. param.ranges.min = paramRanges.min;
  732. param.ranges.max = paramRanges.max;
  733. param.ranges.step = paramRanges.step;
  734. param.ranges.stepSmall = paramRanges.stepSmall;
  735. param.ranges.stepLarge = paramRanges.stepLarge;
  736. param.scalePointCount = 0; // TODO
  737. param.scalePoints = nullptr;
  738. return &param;
  739. }
  740. }
  741. return nullptr;
  742. }
  743. float getParameterValue(const uint32_t index) const
  744. {
  745. if (CarlaPlugin* const plugin = _getFirstPlugin())
  746. {
  747. if (index < plugin->getParameterCount())
  748. return plugin->getParameterValue(index);
  749. }
  750. return 0.0f;
  751. }
  752. const char* getParameterText(const uint32_t index /*, const float value*/) const
  753. {
  754. if (CarlaPlugin* const plugin = _getFirstPlugin())
  755. {
  756. if (index < plugin->getParameterCount())
  757. {
  758. static char strBuf[STR_MAX+1];
  759. carla_zeroChar(strBuf, STR_MAX+1);
  760. plugin->getParameterText(index, /*value,*/ strBuf);
  761. return strBuf;
  762. }
  763. }
  764. return nullptr;
  765. }
  766. // -------------------------------------------------------------------
  767. // Plugin midi-program calls
  768. uint32_t getMidiProgramCount() const
  769. {
  770. if (CarlaPlugin* const plugin = _getFirstPlugin())
  771. return plugin->getMidiProgramCount();
  772. return 0;
  773. }
  774. const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const
  775. {
  776. if (CarlaPlugin* const plugin = _getFirstPlugin())
  777. {
  778. if (index < plugin->getMidiProgramCount())
  779. {
  780. static NativeMidiProgram midiProg;
  781. {
  782. const MidiProgramData& midiProgData(plugin->getMidiProgramData(index));
  783. midiProg.bank = midiProgData.bank;
  784. midiProg.program = midiProgData.program;
  785. midiProg.name = midiProgData.name;
  786. }
  787. return &midiProg;
  788. }
  789. }
  790. return nullptr;
  791. }
  792. // -------------------------------------------------------------------
  793. // Plugin state calls
  794. void setParameterValue(const uint32_t index, const float value)
  795. {
  796. if (CarlaPlugin* const plugin = _getFirstPlugin())
  797. {
  798. if (index < plugin->getParameterCount())
  799. plugin->setParameterValue(index, value, false, false, false);
  800. }
  801. }
  802. void setMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program)
  803. {
  804. if (CarlaPlugin* const plugin = _getFirstPlugin())
  805. plugin->setMidiProgramById(bank, program, false, false, false);
  806. }
  807. // -------------------------------------------------------------------
  808. // Plugin process calls
  809. void activate()
  810. {
  811. #if 0
  812. for (uint32_t i=0; i < pData->curPluginCount; ++i)
  813. {
  814. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  815. if (plugin == nullptr || ! plugin->isEnabled())
  816. continue;
  817. plugin->setActive(true, true, false);
  818. }
  819. #endif
  820. fIsActive = true;
  821. }
  822. void deactivate()
  823. {
  824. fIsActive = false;
  825. #if 0
  826. for (uint32_t i=0; i < pData->curPluginCount; ++i)
  827. {
  828. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  829. if (plugin == nullptr || ! plugin->isEnabled())
  830. continue;
  831. plugin->setActive(false, true, false);
  832. }
  833. #endif
  834. // just in case
  835. runPendingRtEvents();
  836. }
  837. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount)
  838. {
  839. if (pData->curPluginCount == 0 && ! fIsPatchbay)
  840. {
  841. FLOAT_COPY(outBuffer[0], inBuffer[0], frames);
  842. FLOAT_COPY(outBuffer[1], inBuffer[1], frames);
  843. return runPendingRtEvents();;
  844. }
  845. // ---------------------------------------------------------------
  846. // Time Info
  847. const NativeTimeInfo* const timeInfo(pHost->get_time_info(pHost->handle));
  848. pData->timeInfo.playing = timeInfo->playing;
  849. pData->timeInfo.frame = timeInfo->frame;
  850. pData->timeInfo.usecs = timeInfo->usecs;
  851. pData->timeInfo.valid = 0x0;
  852. if (timeInfo->bbt.valid)
  853. {
  854. pData->timeInfo.valid |= EngineTimeInfo::kValidBBT;
  855. pData->timeInfo.bbt.bar = timeInfo->bbt.bar;
  856. pData->timeInfo.bbt.beat = timeInfo->bbt.beat;
  857. pData->timeInfo.bbt.tick = timeInfo->bbt.tick;
  858. pData->timeInfo.bbt.barStartTick = timeInfo->bbt.barStartTick;
  859. pData->timeInfo.bbt.beatsPerBar = timeInfo->bbt.beatsPerBar;
  860. pData->timeInfo.bbt.beatType = timeInfo->bbt.beatType;
  861. pData->timeInfo.bbt.ticksPerBeat = timeInfo->bbt.ticksPerBeat;
  862. pData->timeInfo.bbt.beatsPerMinute = timeInfo->bbt.beatsPerMinute;
  863. }
  864. // ---------------------------------------------------------------
  865. // initialize events
  866. carla_zeroStruct<EngineEvent>(pData->events.in, kMaxEngineEventInternalCount);
  867. carla_zeroStruct<EngineEvent>(pData->events.out, kMaxEngineEventInternalCount);
  868. // ---------------------------------------------------------------
  869. // events input (before processing)
  870. {
  871. uint32_t engineEventIndex = 0;
  872. for (uint32_t i=0; i < midiEventCount && engineEventIndex < kMaxEngineEventInternalCount; ++i)
  873. {
  874. const NativeMidiEvent& midiEvent(midiEvents[i]);
  875. EngineEvent& engineEvent(pData->events.in[engineEventIndex++]);
  876. engineEvent.time = midiEvent.time;
  877. engineEvent.fillFromMidiData(midiEvent.size, midiEvent.data);
  878. if (engineEventIndex >= kMaxEngineEventInternalCount)
  879. break;
  880. }
  881. }
  882. if (fIsPatchbay)
  883. {
  884. // -----------------------------------------------------------
  885. // create audio buffers
  886. //float* inBuf[2] = { inBuffer[0], inBuffer[1] };
  887. //float* outBuf[2] = { outBuffer[0], outBuffer[1] };
  888. //uint32_t bufCount[2] = { 2, 2 };
  889. // -----------------------------------------------------------
  890. // process
  891. //pData->processPatchbay(inBuf, outBuf, bufCount, frames, isOffline());
  892. }
  893. else
  894. {
  895. // -----------------------------------------------------------
  896. // create audio buffers
  897. const float* inBuf[2] = { inBuffer[0], inBuffer[1] };
  898. float* outBuf[2] = { outBuffer[0], outBuffer[1] };
  899. // -----------------------------------------------------------
  900. // process
  901. pData->processRack(inBuf, outBuf, frames, isOffline());
  902. }
  903. // ---------------------------------------------------------------
  904. // events output (after processing)
  905. carla_zeroStruct<EngineEvent>(pData->events.in, kMaxEngineEventInternalCount);
  906. {
  907. NativeMidiEvent midiEvent;
  908. for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i)
  909. {
  910. const EngineEvent& engineEvent(pData->events.out[i]);
  911. if (engineEvent.type == kEngineEventTypeNull)
  912. break;
  913. midiEvent.time = engineEvent.time;
  914. if (engineEvent.type == CarlaBackend::kEngineEventTypeControl)
  915. {
  916. midiEvent.port = 0;
  917. engineEvent.ctrl.convertToMidiData(engineEvent.channel, midiEvent.size, midiEvent.data);
  918. }
  919. else if (engineEvent.type == kEngineEventTypeMidi)
  920. {
  921. if (engineEvent.midi.size > 4 || engineEvent.midi.dataExt != nullptr)
  922. continue;
  923. midiEvent.port = engineEvent.midi.port;
  924. midiEvent.size = engineEvent.midi.size;
  925. midiEvent.data[0] = static_cast<uint8_t>(engineEvent.midi.data[0] + engineEvent.channel);
  926. for (uint8_t j=1; j < midiEvent.size; ++j)
  927. midiEvent.data[j] = engineEvent.midi.data[j];
  928. }
  929. else
  930. {
  931. carla_stderr("Unknown event type...");
  932. continue;
  933. }
  934. pHost->write_midi_event(pHost->handle, &midiEvent);
  935. }
  936. }
  937. runPendingRtEvents();
  938. }
  939. // -------------------------------------------------------------------
  940. // Plugin UI calls
  941. void uiShow(const bool show)
  942. {
  943. if (show)
  944. {
  945. CarlaString path(pHost->resourceDir);
  946. path += "/carla-plugin";
  947. carla_stdout("Trying to start carla-plugin using \"%s\"", path.buffer());
  948. fUiServer.setData(path, pData->sampleRate, pHost->uiName);
  949. fUiServer.start();
  950. for (uint i=0; i < pData->curPluginCount; ++i)
  951. {
  952. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  953. if (plugin != nullptr && plugin->isEnabled())
  954. {
  955. uiServerCallback(ENGINE_CALLBACK_PLUGIN_ADDED, i, 0, 0, 0.0f, plugin->getName());
  956. }
  957. }
  958. }
  959. else
  960. {
  961. fUiServer.stop();
  962. }
  963. }
  964. void uiIdle()
  965. {
  966. CarlaEngine::idle();
  967. fUiServer.idle();
  968. if (! fUiServer.isOk())
  969. return;
  970. for (uint i=0; i < pData->curPluginCount; ++i)
  971. {
  972. const EnginePluginData& plugData(pData->plugins[i]);
  973. const CarlaPlugin* const plugin(pData->plugins[i].plugin);
  974. std::sprintf(fTmpBuf, "PEAKS_%i\n", i);
  975. fUiServer.writeMsg(fTmpBuf);
  976. std::sprintf(fTmpBuf, "%f:%f:%f:%f\n", plugData.insPeak[0], plugData.insPeak[1], plugData.outsPeak[0], plugData.outsPeak[1]);
  977. fUiServer.writeMsg(fTmpBuf);
  978. for (uint32_t j=0, count=plugin->getParameterCount(); j < count; ++j)
  979. {
  980. if (plugin->isParameterOutput(j))
  981. continue;
  982. std::sprintf(fTmpBuf, "PARAMVAL_%i:%i\n", i, j);
  983. fUiServer.writeMsg(fTmpBuf);
  984. std::sprintf(fTmpBuf, "%f\n", plugin->getParameterValue(j));
  985. fUiServer.writeMsg(fTmpBuf);
  986. }
  987. }
  988. switch (fUiServer.getAndResetUiState())
  989. {
  990. case CarlaExternalUI::UiNone:
  991. case CarlaExternalUI::UiShow:
  992. break;
  993. case CarlaExternalUI::UiCrashed:
  994. pHost->dispatcher(pHost->handle, HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f);
  995. break;
  996. case CarlaExternalUI::UiHide:
  997. pHost->ui_closed(pHost->handle);
  998. break;
  999. }
  1000. }
  1001. // -------------------------------------------------------------------
  1002. // Plugin state calls
  1003. char* getState() const
  1004. {
  1005. QString string;
  1006. QTextStream out(&string);
  1007. out << "<?xml version='1.0' encoding='UTF-8'?>\n";
  1008. out << "<!DOCTYPE CARLA-PROJECT>\n";
  1009. out << "<CARLA-PROJECT VERSION='2.0'>\n";
  1010. bool firstPlugin = true;
  1011. char strBuf[STR_MAX+1];
  1012. for (unsigned int i=0; i < pData->curPluginCount; ++i)
  1013. {
  1014. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1015. if (plugin != nullptr && plugin->isEnabled())
  1016. {
  1017. if (! firstPlugin)
  1018. out << "\n";
  1019. strBuf[0] = '\0';
  1020. plugin->getRealName(strBuf);
  1021. //if (strBuf[0] != '\0')
  1022. // out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true));
  1023. QString content;
  1024. fillXmlStringFromSaveState(content, plugin->getSaveState());
  1025. out << " <Plugin>\n";
  1026. out << content;
  1027. out << " </Plugin>\n";
  1028. firstPlugin = false;
  1029. }
  1030. }
  1031. out << "</CARLA-PROJECT>\n";
  1032. return strdup(string.toUtf8().constData());
  1033. }
  1034. void setState(const char* const data)
  1035. {
  1036. QDomDocument xml;
  1037. xml.setContent(QString(data));
  1038. QDomNode xmlNode(xml.documentElement());
  1039. if (xmlNode.toElement().tagName().compare("carla-project", Qt::CaseInsensitive) != 0)
  1040. {
  1041. carla_stderr2("Not a valid Carla project");
  1042. return;
  1043. }
  1044. //bool pluginsAdded = false;
  1045. for (QDomNode node = xmlNode.firstChild(); ! node.isNull(); node = node.nextSibling())
  1046. {
  1047. if (node.toElement().tagName().compare("plugin", Qt::CaseInsensitive) == 0)
  1048. {
  1049. SaveState saveState;
  1050. fillSaveStateFromXmlNode(saveState, node);
  1051. CARLA_SAFE_ASSERT_CONTINUE(saveState.type != nullptr);
  1052. const void* extraStuff = nullptr;
  1053. // check if using GIG, SF2 or SFZ 16outs
  1054. static const char kUse16OutsSuffix[] = " (16 outs)";
  1055. const PluginType ptype(getPluginTypeFromString(saveState.type));
  1056. if (CarlaString(saveState.label).endsWith(kUse16OutsSuffix))
  1057. {
  1058. if (ptype == PLUGIN_FILE_GIG || ptype == PLUGIN_FILE_SF2)
  1059. extraStuff = "true";
  1060. }
  1061. // TODO - proper find&load plugins
  1062. if (addPlugin(ptype, saveState.binary, saveState.name, saveState.label, saveState.uniqueId, extraStuff))
  1063. {
  1064. if (CarlaPlugin* const plugin = getPlugin(pData->curPluginCount-1))
  1065. plugin->loadSaveState(saveState);
  1066. }
  1067. //pluginsAdded = true;
  1068. }
  1069. }
  1070. //if (pluginsAdded)
  1071. // pHost->dispatcher(pHost->handle, HOST_OPCODE_RELOAD_ALL, 0, 0, nullptr, 0.0f);
  1072. }
  1073. // -------------------------------------------------------------------
  1074. public:
  1075. #define handlePtr ((CarlaEngineNative*)handle)
  1076. static NativePluginHandle _instantiateRack(const NativeHostDescriptor* host)
  1077. {
  1078. return new CarlaEngineNative(host, false);
  1079. }
  1080. #ifdef HAVE_JUCE
  1081. static NativePluginHandle _instantiatePatchbay(const NativeHostDescriptor* host)
  1082. {
  1083. return new CarlaEngineNative(host, true);
  1084. }
  1085. #endif
  1086. static void _cleanup(NativePluginHandle handle)
  1087. {
  1088. delete handlePtr;
  1089. }
  1090. static uint32_t _get_parameter_count(NativePluginHandle handle)
  1091. {
  1092. return handlePtr->getParameterCount();
  1093. }
  1094. static const NativeParameter* _get_parameter_info(NativePluginHandle handle, uint32_t index)
  1095. {
  1096. return handlePtr->getParameterInfo(index);
  1097. }
  1098. static float _get_parameter_value(NativePluginHandle handle, uint32_t index)
  1099. {
  1100. return handlePtr->getParameterValue(index);
  1101. }
  1102. static const char* _get_parameter_text(NativePluginHandle handle, uint32_t index /*, float value*/)
  1103. {
  1104. return handlePtr->getParameterText(index /*, value*/);
  1105. }
  1106. static uint32_t _get_midi_program_count(NativePluginHandle handle)
  1107. {
  1108. return handlePtr->getMidiProgramCount();
  1109. }
  1110. static const NativeMidiProgram* _get_midi_program_info(NativePluginHandle handle, uint32_t index)
  1111. {
  1112. return handlePtr->getMidiProgramInfo(index);
  1113. }
  1114. static void _set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  1115. {
  1116. handlePtr->setParameterValue(index, value);
  1117. }
  1118. static void _set_midi_program(NativePluginHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
  1119. {
  1120. handlePtr->setMidiProgram(channel, bank, program);
  1121. }
  1122. static void _ui_show(NativePluginHandle handle, bool show)
  1123. {
  1124. handlePtr->uiShow(show);
  1125. }
  1126. static void _ui_idle(NativePluginHandle handle)
  1127. {
  1128. handlePtr->uiIdle();
  1129. }
  1130. static void _activate(NativePluginHandle handle)
  1131. {
  1132. handlePtr->activate();
  1133. }
  1134. static void _deactivate(NativePluginHandle handle)
  1135. {
  1136. handlePtr->deactivate();
  1137. }
  1138. static void _process(NativePluginHandle handle, float** inBuffer, float** outBuffer, const uint32_t frames, const NativeMidiEvent* midiEvents, uint32_t midiEventCount)
  1139. {
  1140. handlePtr->process(inBuffer, outBuffer, frames, midiEvents, midiEventCount);
  1141. }
  1142. static char* _get_state(NativePluginHandle handle)
  1143. {
  1144. return handlePtr->getState();
  1145. }
  1146. static void _set_state(NativePluginHandle handle, const char* data)
  1147. {
  1148. handlePtr->setState(data);
  1149. }
  1150. static intptr_t _dispatcher(NativePluginHandle handle, NativePluginDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
  1151. {
  1152. switch(opcode)
  1153. {
  1154. case PLUGIN_OPCODE_NULL:
  1155. return 0;
  1156. case PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
  1157. CARLA_SAFE_ASSERT_RETURN(value > 0, 0);
  1158. handlePtr->bufferSizeChanged(static_cast<uint32_t>(value));
  1159. return 0;
  1160. case PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
  1161. handlePtr->sampleRateChanged(static_cast<double>(opt));
  1162. return 0;
  1163. case PLUGIN_OPCODE_OFFLINE_CHANGED:
  1164. handlePtr->offlineModeChanged(value != 0);
  1165. return 0;
  1166. case PLUGIN_OPCODE_UI_NAME_CHANGED:
  1167. //handlePtr->uiNameChanged(static_cast<const char*>(ptr));
  1168. return 0;
  1169. }
  1170. return 0;
  1171. // unused
  1172. (void)index;
  1173. (void)ptr;
  1174. }
  1175. // -------------------------------------------------------------------
  1176. static void _ui_server_callback(void* handle, EngineCallbackOpcode action, uint pluginId, int value1, int value2, float value3, const char* valueStr)
  1177. {
  1178. handlePtr->uiServerCallback(action, pluginId, value1, value2, value3, valueStr);
  1179. }
  1180. // -------------------------------------------------------------------
  1181. #undef handlePtr
  1182. private:
  1183. const NativeHostDescriptor* const pHost;
  1184. const bool fIsPatchbay; // rack if false
  1185. bool fIsActive, fIsRunning;
  1186. CarlaEngineNativeUI fUiServer;
  1187. char fTmpBuf[STR_MAX+1];
  1188. CarlaPlugin* _getFirstPlugin() const noexcept
  1189. {
  1190. if (pData->curPluginCount == 0 || pData->plugins == nullptr)
  1191. return nullptr;
  1192. CarlaPlugin* const plugin(pData->plugins[0].plugin);
  1193. if (plugin == nullptr || ! plugin->isEnabled())
  1194. return nullptr;
  1195. return pData->plugins[0].plugin;
  1196. }
  1197. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNative)
  1198. };
  1199. // -----------------------------------------------------------------------
  1200. static const NativePluginDescriptor carlaRackDesc = {
  1201. /* category */ ::PLUGIN_CATEGORY_OTHER,
  1202. /* hints */ static_cast<NativePluginHints>(::PLUGIN_IS_SYNTH|::PLUGIN_HAS_UI|::PLUGIN_NEEDS_FIXED_BUFFERS|::PLUGIN_NEEDS_SINGLE_THREAD|::PLUGIN_USES_STATE|::PLUGIN_USES_TIME),
  1203. /* supports */ static_cast<NativePluginSupports>(::PLUGIN_SUPPORTS_EVERYTHING),
  1204. /* audioIns */ 2,
  1205. /* audioOuts */ 2,
  1206. /* midiIns */ 1,
  1207. /* midiOuts */ 1,
  1208. /* paramIns */ 0,
  1209. /* paramOuts */ 0,
  1210. /* name */ "Carla-Rack",
  1211. /* label */ "carlarack",
  1212. /* maker */ "falkTX",
  1213. /* copyright */ "GNU GPL v2+",
  1214. CarlaEngineNative::_instantiateRack,
  1215. CarlaEngineNative::_cleanup,
  1216. CarlaEngineNative::_get_parameter_count,
  1217. CarlaEngineNative::_get_parameter_info,
  1218. CarlaEngineNative::_get_parameter_value,
  1219. CarlaEngineNative::_get_parameter_text,
  1220. CarlaEngineNative::_get_midi_program_count,
  1221. CarlaEngineNative::_get_midi_program_info,
  1222. CarlaEngineNative::_set_parameter_value,
  1223. CarlaEngineNative::_set_midi_program,
  1224. /* _set_custom_data */ nullptr,
  1225. CarlaEngineNative::_ui_show,
  1226. CarlaEngineNative::_ui_idle,
  1227. /* _ui_set_parameter_value */ nullptr,
  1228. /* _ui_set_midi_program */ nullptr,
  1229. /* _ui_set_custom_data */ nullptr,
  1230. CarlaEngineNative::_activate,
  1231. CarlaEngineNative::_deactivate,
  1232. CarlaEngineNative::_process,
  1233. CarlaEngineNative::_get_state,
  1234. CarlaEngineNative::_set_state,
  1235. CarlaEngineNative::_dispatcher
  1236. };
  1237. #if 0 //def HAVE_JUCE
  1238. static const NativePluginDescriptor carlaPatchbayDesc = {
  1239. /* category */ ::PLUGIN_CATEGORY_OTHER,
  1240. /* hints */ static_cast<NativePluginHints>(::PLUGIN_IS_SYNTH|::PLUGIN_HAS_UI|::PLUGIN_NEEDS_FIXED_BUFFERS|::PLUGIN_NEEDS_SINGLE_THREAD|::PLUGIN_USES_STATE|::PLUGIN_USES_TIME),
  1241. /* supports */ static_cast<NativePluginSupports>(::PLUGIN_SUPPORTS_EVERYTHING),
  1242. /* audioIns */ 2,
  1243. /* audioOuts */ 2,
  1244. /* midiIns */ 1,
  1245. /* midiOuts */ 1,
  1246. /* paramIns */ 0,
  1247. /* paramOuts */ 0,
  1248. /* name */ "Carla-Patchbay",
  1249. /* label */ "carlapatchbay",
  1250. /* maker */ "falkTX",
  1251. /* copyright */ "GNU GPL v2+",
  1252. CarlaEngineNative::_instantiatePatchbay,
  1253. CarlaEngineNative::_cleanup,
  1254. CarlaEngineNative::_get_parameter_count,
  1255. CarlaEngineNative::_get_parameter_info,
  1256. CarlaEngineNative::_get_parameter_value,
  1257. CarlaEngineNative::_get_parameter_text,
  1258. CarlaEngineNative::_get_midi_program_count,
  1259. CarlaEngineNative::_get_midi_program_info,
  1260. CarlaEngineNative::_set_parameter_value,
  1261. CarlaEngineNative::_set_midi_program,
  1262. /* _set_custom_data */ nullptr,
  1263. CarlaEngineNative::_ui_show,
  1264. CarlaEngineNative::_ui_idle,
  1265. /* _ui_set_parameter_value */ nullptr,
  1266. /* _ui_set_midi_program */ nullptr,
  1267. /* _ui_set_custom_data */ nullptr,
  1268. CarlaEngineNative::_activate,
  1269. CarlaEngineNative::_deactivate,
  1270. CarlaEngineNative::_process,
  1271. CarlaEngineNative::_get_state,
  1272. CarlaEngineNative::_set_state,
  1273. CarlaEngineNative::_dispatcher
  1274. };
  1275. #endif
  1276. // -----------------------------------------------------------------------
  1277. CARLA_BACKEND_END_NAMESPACE
  1278. CARLA_EXPORT
  1279. void carla_register_native_plugin_carla();
  1280. void carla_register_native_plugin_carla()
  1281. {
  1282. CARLA_BACKEND_USE_NAMESPACE;
  1283. carla_register_native_plugin(&carlaRackDesc);
  1284. #if 0 //def HAVE_JUCE
  1285. carla_register_native_plugin(&carlaPatchbayDesc);
  1286. #endif
  1287. }
  1288. // -----------------------------------------------------------------------
  1289. // Extra stuff for linking purposes
  1290. #ifdef CARLA_PLUGIN_EXPORT
  1291. CARLA_BACKEND_START_NAMESPACE
  1292. CarlaEngine* CarlaEngine::newJack() { return nullptr; }
  1293. CarlaEngine* CarlaEngine::newRtAudio(const AudioApi) { return nullptr; }
  1294. unsigned int CarlaEngine::getRtAudioApiCount() { return 0; }
  1295. const char* CarlaEngine::getRtAudioApiName(const unsigned int) { return nullptr; }
  1296. const char* const* CarlaEngine::getRtAudioApiDeviceNames(const unsigned int) { return nullptr; }
  1297. const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const unsigned int, const char* const) { return nullptr; }
  1298. # ifdef HAVE_JUCE
  1299. CarlaEngine* CarlaEngine::newJuce(const AudioApi) { return nullptr; }
  1300. unsigned int CarlaEngine::getJuceApiCount() { return 0; }
  1301. const char* CarlaEngine::getJuceApiName(const unsigned int) { return nullptr; }
  1302. const char* const* CarlaEngine::getJuceApiDeviceNames(const unsigned int) { return nullptr; }
  1303. const EngineDriverDeviceInfo* CarlaEngine::getJuceDeviceInfo(const unsigned int, const char* const) { return nullptr; }
  1304. # endif
  1305. CARLA_BACKEND_END_NAMESPACE
  1306. #ifdef WANT_DSSI
  1307. # include "CarlaDssiUtils.cpp"
  1308. #endif
  1309. #include "CarlaStateUtils.cpp"
  1310. #endif
  1311. // -----------------------------------------------------------------------