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.

CarlaPluginJuce.cpp 44KB

11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 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
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
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287
  1. /*
  2. * Carla Juce Plugin
  3. * Copyright (C) 2013-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 "CarlaPluginInternal.hpp"
  18. #include "CarlaEngine.hpp"
  19. #if (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
  20. #include "CarlaBackendUtils.hpp"
  21. #include "CarlaMathUtils.hpp"
  22. #include "JucePluginWindow.hpp"
  23. #include "juce_audio_processors.h"
  24. using namespace juce;
  25. CARLA_BACKEND_START_NAMESPACE
  26. // -----------------------------------------------------
  27. class CarlaPluginJuce : public CarlaPlugin,
  28. private AudioPlayHead,
  29. private AudioProcessorListener
  30. {
  31. public:
  32. CarlaPluginJuce(CarlaEngine* const engine, const uint id)
  33. : CarlaPlugin(engine, id),
  34. fDesc(),
  35. fInstance(nullptr),
  36. fFormatManager(),
  37. fAudioBuffer(),
  38. fMidiBuffer(),
  39. fPosInfo(),
  40. fChunk(),
  41. fUniqueId(nullptr),
  42. fWindow(),
  43. leakDetector_CarlaPluginJuce()
  44. {
  45. carla_debug("CarlaPluginJuce::CarlaPluginJuce(%p, %i)", engine, id);
  46. fMidiBuffer.ensureSize(2048);
  47. fMidiBuffer.clear();
  48. fPosInfo.resetToDefault();
  49. }
  50. ~CarlaPluginJuce() override
  51. {
  52. carla_debug("CarlaPluginJuce::~CarlaPluginJuce()");
  53. // close UI
  54. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  55. showCustomUI(false);
  56. pData->singleMutex.lock();
  57. pData->masterMutex.lock();
  58. if (pData->client != nullptr && pData->client->isActive())
  59. pData->client->deactivate();
  60. if (pData->active)
  61. {
  62. deactivate();
  63. pData->active = false;
  64. }
  65. if (fInstance != nullptr)
  66. {
  67. delete fInstance;
  68. fInstance = nullptr;
  69. }
  70. clearBuffers();
  71. }
  72. // -------------------------------------------------------------------
  73. // Information (base)
  74. PluginType getType() const noexcept override
  75. {
  76. return getPluginTypeFromString(fDesc.pluginFormatName.toRawUTF8());
  77. }
  78. PluginCategory getCategory() const noexcept override
  79. {
  80. if (fDesc.isInstrument)
  81. return PLUGIN_CATEGORY_SYNTH;
  82. return getPluginCategoryFromName(fDesc.category.toRawUTF8());
  83. }
  84. int64_t getUniqueId() const noexcept override
  85. {
  86. return fDesc.uid;
  87. }
  88. // -------------------------------------------------------------------
  89. // Information (count)
  90. // nothing
  91. // -------------------------------------------------------------------
  92. // Information (current data)
  93. std::size_t getChunkData(void** const dataPtr) noexcept override
  94. {
  95. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
  96. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr, 0);
  97. CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
  98. *dataPtr = nullptr;
  99. try {
  100. fChunk.reset();
  101. fInstance->getStateInformation(fChunk);
  102. } CARLA_SAFE_EXCEPTION_RETURN("CarlaPluginJuce::getChunkData", 0);
  103. if (const std::size_t size = fChunk.getSize())
  104. {
  105. *dataPtr = fChunk.getData();
  106. return size;
  107. }
  108. return 0;
  109. }
  110. // -------------------------------------------------------------------
  111. // Information (per-plugin data)
  112. uint getOptionsAvailable() const noexcept override
  113. {
  114. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr, 0x0);
  115. uint options = 0x0;
  116. options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  117. options |= PLUGIN_OPTION_USE_CHUNKS;
  118. if (fInstance->acceptsMidi())
  119. {
  120. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  121. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  122. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  123. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  124. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  125. }
  126. return options;
  127. }
  128. float getParameterValue(const uint32_t parameterId) const noexcept override
  129. {
  130. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
  131. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr, 0.0f);
  132. return fInstance->getParameter(static_cast<int>(parameterId));
  133. }
  134. void getLabel(char* const strBuf) const noexcept override
  135. {
  136. if (fDesc.pluginFormatName == "AU" || fDesc.pluginFormatName == "AudioUnit")
  137. std::strncpy(strBuf, fDesc.fileOrIdentifier.toRawUTF8(), STR_MAX);
  138. else
  139. std::strncpy(strBuf, fDesc.name.toRawUTF8(), STR_MAX);
  140. }
  141. void getMaker(char* const strBuf) const noexcept override
  142. {
  143. std::strncpy(strBuf, fDesc.manufacturerName.toRawUTF8(), STR_MAX);
  144. }
  145. void getCopyright(char* const strBuf) const noexcept override
  146. {
  147. getMaker(strBuf);
  148. }
  149. void getRealName(char* const strBuf) const noexcept override
  150. {
  151. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,);
  152. std::strncpy(strBuf, fInstance->getName().toRawUTF8(), STR_MAX);
  153. }
  154. void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
  155. {
  156. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  157. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,);
  158. std::strncpy(strBuf, fInstance->getParameterName(static_cast<int>(parameterId), STR_MAX).toRawUTF8(), STR_MAX);
  159. }
  160. void getParameterText(const uint32_t parameterId, char* const strBuf) const noexcept override
  161. {
  162. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  163. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,);
  164. std::strncpy(strBuf, fInstance->getParameterText(static_cast<int>(parameterId), STR_MAX).toRawUTF8(), STR_MAX);
  165. }
  166. void getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
  167. {
  168. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  169. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,);
  170. std::strncpy(strBuf, fInstance->getParameterLabel(static_cast<int>(parameterId)).toRawUTF8(), STR_MAX);
  171. }
  172. // -------------------------------------------------------------------
  173. // Set data (state)
  174. // nothing
  175. // -------------------------------------------------------------------
  176. // Set data (internal stuff)
  177. void setName(const char* const newName) override
  178. {
  179. CarlaPlugin::setName(newName);
  180. if (fWindow != nullptr)
  181. {
  182. String uiName(pData->name);
  183. uiName += " (GUI)";
  184. fWindow->setName(uiName);
  185. }
  186. }
  187. // -------------------------------------------------------------------
  188. // Set data (plugin-specific stuff)
  189. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  190. {
  191. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  192. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,);
  193. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  194. fInstance->setParameter(static_cast<int>(parameterId), value);
  195. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  196. }
  197. void setChunkData(const void* const data, const std::size_t dataSize) override
  198. {
  199. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,);
  200. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,);
  201. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  202. CARLA_SAFE_ASSERT_RETURN(dataSize > 0,);
  203. {
  204. const ScopedSingleProcessLocker spl(this, true);
  205. fInstance->setStateInformation(data, static_cast<int>(dataSize));
  206. }
  207. #if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE)
  208. const bool sendOsc(pData->engine->isOscControlRegistered());
  209. #else
  210. const bool sendOsc(false);
  211. #endif
  212. pData->updateParameterValues(this, sendOsc, true, false);
  213. }
  214. void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  215. {
  216. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,);
  217. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),);
  218. if (index >= 0)
  219. {
  220. const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
  221. try {
  222. fInstance->setCurrentProgram(index);
  223. } CARLA_SAFE_EXCEPTION("setCurrentProgram");
  224. }
  225. CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback);
  226. }
  227. // -------------------------------------------------------------------
  228. // Set ui stuff
  229. void showCustomUI(const bool yesNo) override
  230. {
  231. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,);
  232. if (yesNo)
  233. {
  234. if (fWindow == nullptr)
  235. {
  236. String uiName(pData->name);
  237. uiName += " (GUI)";
  238. fWindow = new JucePluginWindow();
  239. fWindow->setName(uiName);
  240. }
  241. if (AudioProcessorEditor* const editor = fInstance->createEditorIfNeeded())
  242. fWindow->show(editor);
  243. }
  244. else
  245. {
  246. if (fWindow != nullptr)
  247. fWindow->hide();
  248. if (AudioProcessorEditor* const editor = fInstance->getActiveEditor())
  249. delete editor;
  250. fWindow = nullptr;
  251. }
  252. }
  253. void uiIdle() override
  254. {
  255. if (fWindow != nullptr)
  256. {
  257. if (fWindow->wasClosedByUser())
  258. {
  259. showCustomUI(false);
  260. pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
  261. }
  262. }
  263. CarlaPlugin::uiIdle();
  264. }
  265. // -------------------------------------------------------------------
  266. // Plugin state
  267. void reload() override
  268. {
  269. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  270. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,);
  271. carla_debug("CarlaPluginJuce::reload() - start");
  272. const EngineProcessMode processMode(pData->engine->getProccessMode());
  273. // Safely disable plugin for reload
  274. const ScopedDisabler sd(this);
  275. if (pData->active)
  276. deactivate();
  277. clearBuffers();
  278. fInstance->refreshParameterList();
  279. uint32_t aIns, aOuts, mIns, mOuts, params;
  280. mIns = mOuts = 0;
  281. bool needsCtrlIn, needsCtrlOut;
  282. needsCtrlIn = needsCtrlOut = false;
  283. aIns = (fInstance->getNumInputChannels() > 0) ? static_cast<uint32_t>(fInstance->getNumInputChannels()) : 0;
  284. aOuts = (fInstance->getNumOutputChannels() > 0) ? static_cast<uint32_t>(fInstance->getNumOutputChannels()) : 0;
  285. params = (fInstance->getNumParameters() > 0) ? static_cast<uint32_t>(fInstance->getNumParameters()) : 0;
  286. if (fInstance->acceptsMidi())
  287. {
  288. mIns = 1;
  289. needsCtrlIn = true;
  290. }
  291. if (fInstance->producesMidi())
  292. {
  293. mOuts = 1;
  294. needsCtrlOut = true;
  295. }
  296. if (aIns > 0)
  297. {
  298. pData->audioIn.createNew(aIns);
  299. }
  300. if (aOuts > 0)
  301. {
  302. pData->audioOut.createNew(aOuts);
  303. needsCtrlIn = true;
  304. }
  305. if (params > 0)
  306. {
  307. pData->param.createNew(params, false);
  308. needsCtrlIn = true;
  309. }
  310. const uint portNameSize(pData->engine->getMaxPortNameSize());
  311. CarlaString portName;
  312. // Audio Ins
  313. for (uint32_t j=0; j < aIns; ++j)
  314. {
  315. portName.clear();
  316. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  317. {
  318. portName = pData->name;
  319. portName += ":";
  320. }
  321. if (aIns > 1)
  322. {
  323. portName += "input_";
  324. portName += CarlaString(j+1);
  325. }
  326. else
  327. portName += "input";
  328. portName.truncate(portNameSize);
  329. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true);
  330. pData->audioIn.ports[j].rindex = j;
  331. }
  332. // Audio Outs
  333. for (uint32_t j=0; j < aOuts; ++j)
  334. {
  335. portName.clear();
  336. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  337. {
  338. portName = pData->name;
  339. portName += ":";
  340. }
  341. if (aOuts > 1)
  342. {
  343. portName += "output_";
  344. portName += CarlaString(j+1);
  345. }
  346. else
  347. portName += "output";
  348. portName.truncate(portNameSize);
  349. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
  350. pData->audioOut.ports[j].rindex = j;
  351. }
  352. for (uint32_t j=0; j < params; ++j)
  353. {
  354. pData->param.data[j].type = PARAMETER_INPUT;
  355. pData->param.data[j].index = static_cast<int32_t>(j);
  356. pData->param.data[j].rindex = static_cast<int32_t>(j);
  357. float min, max, def, step, stepSmall, stepLarge;
  358. // TODO
  359. //const int numSteps(fInstance->getParameterNumSteps(static_cast<int>(j)));
  360. {
  361. min = 0.0f;
  362. max = 1.0f;
  363. step = 0.001f;
  364. stepSmall = 0.0001f;
  365. stepLarge = 0.1f;
  366. }
  367. pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
  368. #ifndef BUILD_BRIDGE
  369. pData->param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT;
  370. #endif
  371. if (fInstance->isParameterAutomatable(static_cast<int>(j)))
  372. pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
  373. // FIXME?
  374. def = fInstance->getParameterDefaultValue(static_cast<int>(j));
  375. if (def < min)
  376. def = min;
  377. else if (def > max)
  378. def = max;
  379. pData->param.ranges[j].min = min;
  380. pData->param.ranges[j].max = max;
  381. pData->param.ranges[j].def = def;
  382. pData->param.ranges[j].step = step;
  383. pData->param.ranges[j].stepSmall = stepSmall;
  384. pData->param.ranges[j].stepLarge = stepLarge;
  385. }
  386. if (needsCtrlIn)
  387. {
  388. portName.clear();
  389. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  390. {
  391. portName = pData->name;
  392. portName += ":";
  393. }
  394. portName += "events-in";
  395. portName.truncate(portNameSize);
  396. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true);
  397. }
  398. if (needsCtrlOut)
  399. {
  400. portName.clear();
  401. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  402. {
  403. portName = pData->name;
  404. portName += ":";
  405. }
  406. portName += "events-out";
  407. portName.truncate(portNameSize);
  408. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false);
  409. }
  410. // plugin hints
  411. pData->hints = 0x0;
  412. pData->hints |= PLUGIN_NEEDS_FIXED_BUFFERS;
  413. if (fDesc.isInstrument)
  414. pData->hints |= PLUGIN_IS_SYNTH;
  415. if (fInstance->hasEditor())
  416. {
  417. pData->hints |= PLUGIN_HAS_CUSTOM_UI;
  418. pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD;
  419. }
  420. if (aOuts > 0 && (aIns == aOuts || aIns == 1))
  421. pData->hints |= PLUGIN_CAN_DRYWET;
  422. if (aOuts > 0)
  423. pData->hints |= PLUGIN_CAN_VOLUME;
  424. if (aOuts >= 2 && aOuts % 2 == 0)
  425. pData->hints |= PLUGIN_CAN_BALANCE;
  426. // extra plugin hints
  427. pData->extraHints = 0x0;
  428. if (mIns > 0)
  429. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
  430. if (mOuts > 0)
  431. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT;
  432. if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0))
  433. pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
  434. fInstance->setPlayConfigDetails(static_cast<int>(aIns), static_cast<int>(aOuts), pData->engine->getSampleRate(), static_cast<int>(pData->engine->getBufferSize()));
  435. bufferSizeChanged(pData->engine->getBufferSize());
  436. reloadPrograms(true);
  437. if (pData->active)
  438. activate();
  439. carla_debug("CarlaPluginJuce::reload() - end");
  440. }
  441. void reloadPrograms(const bool doInit) override
  442. {
  443. carla_debug("CarlaPluginJuce::reloadPrograms(%s)", bool2str(doInit));
  444. const uint32_t oldCount = pData->prog.count;
  445. const int32_t current = pData->prog.current;
  446. // Delete old programs
  447. pData->prog.clear();
  448. // Query new programs
  449. uint32_t newCount = (fInstance->getNumPrograms() > 0) ? static_cast<uint32_t>(fInstance->getNumPrograms()) : 0;
  450. if (newCount > 0)
  451. {
  452. pData->prog.createNew(newCount);
  453. // Update names
  454. for (int i=0, count=fInstance->getNumPrograms(); i<count; ++i)
  455. pData->prog.names[i] = carla_strdup(fInstance->getProgramName(i).toRawUTF8());
  456. }
  457. #if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE)
  458. // Update OSC Names
  459. if (pData->engine->isOscControlRegistered())
  460. {
  461. pData->engine->oscSend_control_set_program_count(pData->id, newCount);
  462. for (uint32_t i=0; i < newCount; ++i)
  463. pData->engine->oscSend_control_set_program_name(pData->id, i, pData->prog.names[i]);
  464. }
  465. #endif
  466. if (doInit)
  467. {
  468. if (newCount > 0)
  469. setProgram(0, false, false, false);
  470. }
  471. else
  472. {
  473. // Check if current program is invalid
  474. bool programChanged = false;
  475. if (newCount == oldCount+1)
  476. {
  477. // one program added, probably created by user
  478. pData->prog.current = static_cast<int32_t>(oldCount);
  479. programChanged = true;
  480. }
  481. else if (current < 0 && newCount > 0)
  482. {
  483. // programs exist now, but not before
  484. pData->prog.current = 0;
  485. programChanged = true;
  486. }
  487. else if (current >= 0 && newCount == 0)
  488. {
  489. // programs existed before, but not anymore
  490. pData->prog.current = -1;
  491. programChanged = true;
  492. }
  493. else if (current >= static_cast<int32_t>(newCount))
  494. {
  495. // current program > count
  496. pData->prog.current = 0;
  497. programChanged = true;
  498. }
  499. else
  500. {
  501. // no change
  502. pData->prog.current = current;
  503. }
  504. if (programChanged)
  505. {
  506. setProgram(pData->prog.current, true, true, true);
  507. }
  508. else
  509. {
  510. // Program was changed during update, re-set it
  511. if (pData->prog.current >= 0)
  512. fInstance->setCurrentProgram(pData->prog.current);
  513. }
  514. pData->engine->callback(ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0.0f, nullptr);
  515. }
  516. }
  517. // -------------------------------------------------------------------
  518. // Plugin processing
  519. void activate() noexcept override
  520. {
  521. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,);
  522. try {
  523. fInstance->prepareToPlay(pData->engine->getSampleRate(), static_cast<int>(pData->engine->getBufferSize()));
  524. } catch(...) {}
  525. }
  526. void deactivate() noexcept override
  527. {
  528. CARLA_SAFE_ASSERT_RETURN(fInstance != nullptr,);
  529. try {
  530. fInstance->releaseResources();
  531. } catch(...) {}
  532. }
  533. void process(const float** const audioIn, float** const audioOut, const float** const, float** const, const uint32_t frames) override
  534. {
  535. // --------------------------------------------------------------------------------------------------------
  536. // Check if active
  537. if (! pData->active)
  538. {
  539. // disable any output sound
  540. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  541. FloatVectorOperations::clear(audioOut[i], static_cast<int>(frames));
  542. return;
  543. }
  544. // --------------------------------------------------------------------------------------------------------
  545. // Check if needs reset
  546. if (pData->needsReset)
  547. {
  548. fInstance->reset();
  549. pData->needsReset = false;
  550. }
  551. // --------------------------------------------------------------------------------------------------------
  552. // Event Input
  553. fMidiBuffer.clear();
  554. if (pData->event.portIn != nullptr)
  555. {
  556. // ----------------------------------------------------------------------------------------------------
  557. // MIDI Input (External)
  558. if (pData->extNotes.mutex.tryLock())
  559. {
  560. for (RtLinkedList<ExternalMidiNote>::Itenerator it = pData->extNotes.data.begin(); it.valid(); it.next())
  561. {
  562. const ExternalMidiNote& note(it.getValue());
  563. CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  564. uint8_t midiEvent[3];
  565. midiEvent[0] = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT));
  566. midiEvent[1] = note.note;
  567. midiEvent[2] = note.velo;
  568. fMidiBuffer.addEvent(midiEvent, 3, 0);
  569. }
  570. pData->extNotes.data.clear();
  571. pData->extNotes.mutex.unlock();
  572. } // End of MIDI Input (External)
  573. // ----------------------------------------------------------------------------------------------------
  574. // Event Input (System)
  575. #ifndef BUILD_BRIDGE
  576. bool allNotesOffSent = false;
  577. #endif
  578. for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i)
  579. {
  580. const EngineEvent& event(pData->event.portIn->getEvent(i));
  581. if (event.time >= frames)
  582. continue;
  583. switch (event.type)
  584. {
  585. case kEngineEventTypeNull:
  586. break;
  587. case kEngineEventTypeControl: {
  588. const EngineControlEvent& ctrlEvent(event.ctrl);
  589. switch (ctrlEvent.type)
  590. {
  591. case kEngineControlEventTypeNull:
  592. break;
  593. case kEngineControlEventTypeParameter: {
  594. #ifndef BUILD_BRIDGE
  595. // Control backend stuff
  596. if (event.channel == pData->ctrlChannel)
  597. {
  598. float value;
  599. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
  600. {
  601. value = ctrlEvent.value;
  602. setDryWet(value, false, false);
  603. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
  604. break;
  605. }
  606. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
  607. {
  608. value = ctrlEvent.value*127.0f/100.0f;
  609. setVolume(value, false, false);
  610. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
  611. break;
  612. }
  613. if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
  614. {
  615. float left, right;
  616. value = ctrlEvent.value/0.5f - 1.0f;
  617. if (value < 0.0f)
  618. {
  619. left = -1.0f;
  620. right = (value*2.0f)+1.0f;
  621. }
  622. else if (value > 0.0f)
  623. {
  624. left = (value*2.0f)-1.0f;
  625. right = 1.0f;
  626. }
  627. else
  628. {
  629. left = -1.0f;
  630. right = 1.0f;
  631. }
  632. setBalanceLeft(left, false, false);
  633. setBalanceRight(right, false, false);
  634. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  635. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  636. break;
  637. }
  638. }
  639. #endif
  640. // Control plugin parameters
  641. uint32_t k;
  642. for (k=0; k < pData->param.count; ++k)
  643. {
  644. if (pData->param.data[k].midiChannel != event.channel)
  645. continue;
  646. if (pData->param.data[k].midiCC != ctrlEvent.param)
  647. continue;
  648. if (pData->param.data[k].type != PARAMETER_INPUT)
  649. continue;
  650. if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
  651. continue;
  652. float value;
  653. if (pData->param.data[k].hints & PARAMETER_IS_BOOLEAN)
  654. {
  655. value = (ctrlEvent.value < 0.5f) ? pData->param.ranges[k].min : pData->param.ranges[k].max;
  656. }
  657. else
  658. {
  659. value = pData->param.ranges[k].getUnnormalizedValue(ctrlEvent.value);
  660. if (pData->param.data[k].hints & PARAMETER_IS_INTEGER)
  661. value = std::rint(value);
  662. }
  663. setParameterValue(k, value, false, false, false);
  664. pData->postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value);
  665. break;
  666. }
  667. // check if event is already handled
  668. if (k != pData->param.count)
  669. break;
  670. if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_CONTROL)
  671. {
  672. uint8_t midiData[3];
  673. midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
  674. midiData[1] = uint8_t(ctrlEvent.param);
  675. midiData[2] = uint8_t(ctrlEvent.value*127.0f);
  676. fMidiBuffer.addEvent(midiData, 3, static_cast<int>(event.time));
  677. }
  678. break;
  679. } // case kEngineControlEventTypeParameter
  680. case kEngineControlEventTypeMidiBank:
  681. break;
  682. case kEngineControlEventTypeMidiProgram:
  683. if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  684. {
  685. if (ctrlEvent.param < pData->prog.count)
  686. {
  687. setProgram(ctrlEvent.param, false, false, false);
  688. pData->postponeRtEvent(kPluginPostRtEventProgramChange, ctrlEvent.param, 0, 0.0f);
  689. break;
  690. }
  691. }
  692. break;
  693. case kEngineControlEventTypeAllSoundOff:
  694. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  695. {
  696. uint8_t midiData[3];
  697. midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
  698. midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF;
  699. midiData[2] = 0;
  700. fMidiBuffer.addEvent(midiData, 3, static_cast<int>(event.time));
  701. }
  702. break;
  703. case kEngineControlEventTypeAllNotesOff:
  704. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  705. {
  706. #ifndef BUILD_BRIDGE
  707. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  708. {
  709. allNotesOffSent = true;
  710. sendMidiAllNotesOffToCallback();
  711. }
  712. #endif
  713. uint8_t midiData[3];
  714. midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
  715. midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF;
  716. midiData[2] = 0;
  717. fMidiBuffer.addEvent(midiData, 3, static_cast<int>(event.time));
  718. }
  719. break;
  720. } // switch (ctrlEvent.type)
  721. break;
  722. } // case kEngineEventTypeControl
  723. case kEngineEventTypeMidi: {
  724. const EngineMidiEvent& midiEvent(event.midi);
  725. const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data);
  726. uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData));
  727. if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
  728. continue;
  729. if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
  730. continue;
  731. if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
  732. continue;
  733. if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
  734. continue;
  735. // Fix bad note-off
  736. if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0)
  737. status = MIDI_STATUS_NOTE_OFF;
  738. // put back channel in data
  739. uint8_t midiData2[midiEvent.size];
  740. midiData2[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT));
  741. std::memcpy(midiData2+1, midiData+1, static_cast<std::size_t>(midiEvent.size-1));
  742. fMidiBuffer.addEvent(midiData2, midiEvent.size, static_cast<int>(event.time));
  743. if (status == MIDI_STATUS_NOTE_ON)
  744. pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiData[1], midiData[2]);
  745. else if (status == MIDI_STATUS_NOTE_OFF)
  746. pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiData[1], 0.0f);
  747. } break;
  748. } // switch (event.type)
  749. }
  750. pData->postRtEvents.trySplice();
  751. } // End of Event Input
  752. // --------------------------------------------------------------------------------------------------------
  753. // Set TimeInfo
  754. const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
  755. fPosInfo.isPlaying = timeInfo.playing;
  756. if (timeInfo.valid & EngineTimeInfo::kValidBBT)
  757. {
  758. const double ppqBar = double(timeInfo.bbt.bar - 1) * timeInfo.bbt.beatsPerBar;
  759. const double ppqBeat = double(timeInfo.bbt.beat - 1);
  760. const double ppqTick = double(timeInfo.bbt.tick) / timeInfo.bbt.ticksPerBeat;
  761. fPosInfo.bpm = timeInfo.bbt.beatsPerMinute;
  762. fPosInfo.timeSigNumerator = static_cast<int>(timeInfo.bbt.beatsPerBar);
  763. fPosInfo.timeSigDenominator = static_cast<int>(timeInfo.bbt.beatType);
  764. fPosInfo.timeInSamples = static_cast<int64_t>(timeInfo.frame);
  765. fPosInfo.timeInSeconds = static_cast<double>(fPosInfo.timeInSamples)/pData->engine->getSampleRate();
  766. fPosInfo.ppqPosition = ppqBar + ppqBeat + ppqTick;
  767. fPosInfo.ppqPositionOfLastBarStart = ppqBar;
  768. }
  769. // --------------------------------------------------------------------------------------------------------
  770. // Process
  771. processSingle(audioIn, audioOut, frames);
  772. }
  773. bool processSingle(const float** const inBuffer, float** const outBuffer, const uint32_t frames)
  774. {
  775. CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
  776. if (pData->audioIn.count > 0)
  777. {
  778. CARLA_SAFE_ASSERT_RETURN(inBuffer != nullptr, false);
  779. }
  780. if (pData->audioOut.count > 0)
  781. {
  782. CARLA_SAFE_ASSERT_RETURN(outBuffer != nullptr, false);
  783. }
  784. // --------------------------------------------------------------------------------------------------------
  785. // Try lock, silence otherwise
  786. if (pData->engine->isOffline())
  787. {
  788. pData->singleMutex.lock();
  789. }
  790. else if (! pData->singleMutex.tryLock())
  791. {
  792. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  793. FloatVectorOperations::clear(outBuffer[i], static_cast<int>(frames));
  794. return false;
  795. }
  796. // --------------------------------------------------------------------------------------------------------
  797. // Set audio in buffers
  798. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  799. fAudioBuffer.copyFrom(static_cast<int>(i), 0, inBuffer[i], static_cast<int>(frames));
  800. // --------------------------------------------------------------------------------------------------------
  801. // Run plugin
  802. fInstance->processBlock(fAudioBuffer, fMidiBuffer);
  803. // --------------------------------------------------------------------------------------------------------
  804. // Set audio out buffers
  805. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  806. FloatVectorOperations::copy(outBuffer[i], fAudioBuffer.getReadPointer(static_cast<int>(i)), static_cast<int>(frames));
  807. // --------------------------------------------------------------------------------------------------------
  808. // Midi out
  809. if (! fMidiBuffer.isEmpty())
  810. {
  811. if (pData->event.portOut != nullptr)
  812. {
  813. const uint8* midiEventData;
  814. int midiEventSize, midiEventPosition;
  815. for (MidiBuffer::Iterator i(fMidiBuffer); i.getNextEvent(midiEventData, midiEventSize, midiEventPosition);)
  816. {
  817. CARLA_SAFE_ASSERT_BREAK(midiEventPosition >= 0 && midiEventPosition < static_cast<int>(frames));
  818. CARLA_SAFE_ASSERT_BREAK(midiEventSize > 0);
  819. if (! pData->event.portOut->writeMidiEvent(static_cast<uint32_t>(midiEventPosition), static_cast<uint8_t>(midiEventSize), midiEventData))
  820. break;
  821. }
  822. }
  823. fMidiBuffer.clear();
  824. }
  825. // --------------------------------------------------------------------------------------------------------
  826. pData->singleMutex.unlock();
  827. return true;
  828. }
  829. void bufferSizeChanged(const uint32_t newBufferSize) override
  830. {
  831. CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
  832. carla_debug("CarlaPluginJuce::bufferSizeChanged(%i)", newBufferSize);
  833. fAudioBuffer.setSize(static_cast<int>(std::max<uint32_t>(pData->audioIn.count, pData->audioOut.count)), static_cast<int>(newBufferSize));
  834. if (pData->active)
  835. {
  836. deactivate();
  837. activate();
  838. }
  839. }
  840. void sampleRateChanged(const double newSampleRate) override
  841. {
  842. CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
  843. carla_debug("CarlaPluginJuce::sampleRateChanged(%g)", newSampleRate);
  844. if (pData->active)
  845. {
  846. deactivate();
  847. activate();
  848. }
  849. }
  850. // -------------------------------------------------------------------
  851. // Plugin buffers
  852. // nothing
  853. // -------------------------------------------------------------------
  854. // Post-poned UI Stuff
  855. // nothing
  856. // -------------------------------------------------------------------
  857. void* getNativeHandle() const noexcept override
  858. {
  859. return (fInstance != nullptr) ? fInstance->getPlatformSpecificData() : nullptr;
  860. }
  861. // -------------------------------------------------------------------
  862. protected:
  863. void audioProcessorParameterChanged(AudioProcessor*, int index, float value) override
  864. {
  865. CARLA_SAFE_ASSERT_RETURN(index >= 0,);
  866. const uint32_t uindex(static_cast<uint32_t>(index));
  867. const float fixedValue(pData->param.getFixedValue(uindex, value));
  868. CarlaPlugin::setParameterValue(static_cast<uint32_t>(index), fixedValue, false, true, true);
  869. }
  870. void audioProcessorChanged(AudioProcessor*) override
  871. {
  872. pData->engine->callback(ENGINE_CALLBACK_UPDATE, pData->id, 0, 0, 0.0f, nullptr);
  873. }
  874. void audioProcessorParameterChangeGestureBegin(AudioProcessor*, int) override {}
  875. void audioProcessorParameterChangeGestureEnd(AudioProcessor*, int) override {}
  876. bool getCurrentPosition(CurrentPositionInfo& result) override
  877. {
  878. carla_copyStruct<CurrentPositionInfo>(result, fPosInfo);
  879. return true;
  880. }
  881. // -------------------------------------------------------------------
  882. public:
  883. bool init(const char* const filename, const char* const name, const char* const label, const int64_t uniqueId, const char* const format)
  884. {
  885. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  886. // ---------------------------------------------------------------
  887. // first checks
  888. if (pData->client != nullptr)
  889. {
  890. pData->engine->setLastError("Plugin client is already registered");
  891. return false;
  892. }
  893. if (format == nullptr || format[0] == '\0')
  894. {
  895. pData->engine->setLastError("null format");
  896. return false;
  897. }
  898. // AU and VST3 require label
  899. if (std::strcmp(format, "AU") == 0 || std::strcmp(format, "VST3") == 0)
  900. {
  901. if (label == nullptr || label[0] == '\0')
  902. {
  903. pData->engine->setLastError("null label");
  904. return false;
  905. }
  906. }
  907. if (std::strcmp(format, "AU") == 0)
  908. {
  909. fDesc.fileOrIdentifier = label;
  910. }
  911. else
  912. {
  913. // VST2 and VST3 require filename
  914. if (filename == nullptr || filename[0] == '\0')
  915. {
  916. pData->engine->setLastError("null filename");
  917. return false;
  918. }
  919. String jfilename(filename);
  920. #ifdef CARLA_OS_WIN
  921. // Fix for wine usage
  922. if (juce_isRunningInWine() && filename[0] == '/')
  923. {
  924. jfilename.replace("/", "\\");
  925. jfilename = "Z:" + jfilename;
  926. }
  927. #endif
  928. fDesc.fileOrIdentifier = jfilename;
  929. fDesc.uid = static_cast<int>(uniqueId);
  930. if (label != nullptr && label[0] != '\0')
  931. fDesc.name = label;
  932. }
  933. fDesc.pluginFormatName = format;
  934. fFormatManager.addDefaultFormats();
  935. String error;
  936. fInstance = fFormatManager.createPluginInstance(fDesc, 44100, 512, error);
  937. if (fInstance == nullptr)
  938. {
  939. pData->engine->setLastError(error.toRawUTF8());
  940. return false;
  941. }
  942. fInstance->fillInPluginDescription(fDesc);
  943. fInstance->setPlayHead(this);
  944. fInstance->addListener(this);
  945. // ---------------------------------------------------------------
  946. // get info
  947. if (name != nullptr && name[0] != '\0')
  948. pData->name = pData->engine->getUniquePluginName(name);
  949. else
  950. pData->name = pData->engine->getUniquePluginName(fInstance->getName().toRawUTF8());
  951. pData->filename = carla_strdup(filename);
  952. // ---------------------------------------------------------------
  953. // register client
  954. pData->client = pData->engine->addClient(this);
  955. if (pData->client == nullptr || ! pData->client->isOk())
  956. {
  957. pData->engine->setLastError("Failed to register plugin client");
  958. return false;
  959. }
  960. // ---------------------------------------------------------------
  961. // set default options
  962. pData->options = 0x0;
  963. pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
  964. pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  965. pData->options |= PLUGIN_OPTION_USE_CHUNKS;
  966. if (fInstance->acceptsMidi())
  967. {
  968. pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  969. pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  970. pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
  971. pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  972. }
  973. return true;
  974. }
  975. private:
  976. PluginDescription fDesc;
  977. AudioPluginInstance* fInstance;
  978. AudioPluginFormatManager fFormatManager;
  979. AudioSampleBuffer fAudioBuffer;
  980. MidiBuffer fMidiBuffer;
  981. CurrentPositionInfo fPosInfo;
  982. MemoryBlock fChunk;
  983. const char* fUniqueId;
  984. ScopedPointer<JucePluginWindow> fWindow;
  985. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginJuce)
  986. };
  987. CARLA_BACKEND_END_NAMESPACE
  988. #endif // defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  989. // -------------------------------------------------------------------------------------------------------------------
  990. CARLA_BACKEND_START_NAMESPACE
  991. CarlaPlugin* CarlaPlugin::newJuce(const Initializer& init, const char* const format)
  992. {
  993. carla_debug("CarlaPlugin::newJuce({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "}, %s)", init.engine, init.filename, init.name, init.label, init.uniqueId, format);
  994. #if (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
  995. CarlaPluginJuce* const plugin(new CarlaPluginJuce(init.engine, init.id));
  996. if (! plugin->init(init.filename, init.name, init.label, init.uniqueId, format))
  997. {
  998. delete plugin;
  999. return nullptr;
  1000. }
  1001. return plugin;
  1002. #else
  1003. init.engine->setLastError("Juce plugin not available");
  1004. return nullptr;
  1005. (void)format;
  1006. #endif
  1007. }
  1008. CARLA_BACKEND_END_NAMESPACE
  1009. // -------------------------------------------------------------------------------------------------------------------